Skip to content

Commit b9c57d3

Browse files
committedApr 1, 2025·
LibJS: Use xorshift128++ PRNG for Math.random()
This is the same PRNG used by major browser engines, and although it's a step down in randomness, it massively improves performance of Math.random(). 1.20x speedup on JetStream3/sync-file-system.js :^)
1 parent 3bc6870 commit b9c57d3

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed
 

‎Libraries/LibJS/Runtime/MathObject.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,14 +793,55 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::pow)
793793
return pow_impl(vm, vm.argument(0), vm.argument(1));
794794
}
795795

796+
class XorShift128PlusPlusRNG {
797+
public:
798+
XorShift128PlusPlusRNG()
799+
{
800+
u64 seed = get_random<u32>();
801+
m_low = splitmix64(seed);
802+
m_high = splitmix64(seed);
803+
}
804+
805+
double get()
806+
{
807+
u64 value = advance() & ((1ULL << 53) - 1);
808+
return value * (1.0 / (1ULL << 53));
809+
}
810+
811+
private:
812+
u64 splitmix64(u64& state)
813+
{
814+
u64 z = (state += 0x9e3779b97f4a7c15ULL);
815+
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
816+
z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
817+
return z ^ (z >> 31);
818+
}
819+
820+
u64 advance()
821+
{
822+
u64 s1 = m_low;
823+
u64 const s0 = m_high;
824+
u64 const result = s0 + s1;
825+
m_low = s0;
826+
s1 ^= s1 << 23;
827+
s1 ^= s1 >> 17;
828+
s1 ^= s0 ^ (s0 >> 26);
829+
m_high = s1;
830+
return result + s1;
831+
}
832+
833+
u64 m_low { 0 };
834+
u64 m_high { 0 };
835+
};
836+
796837
// 21.3.2.27 Math.random ( ), https://tc39.es/ecma262/#sec-math.random
797838
JS_DEFINE_NATIVE_FUNCTION(MathObject::random)
798839
{
799840
// This function returns a Number value with positive sign, greater than or equal to +0𝔽 but strictly less than 1𝔽,
800841
// chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an
801842
// implementation-defined algorithm or strategy.
802-
double r = (double)get_random<u32>() / (double)UINT32_MAX;
803-
return Value(r);
843+
static XorShift128PlusPlusRNG rng;
844+
return rng.get();
804845
}
805846

806847
// 21.3.2.28 Math.round ( x ), https://tc39.es/ecma262/#sec-math.round

0 commit comments

Comments
 (0)
Please sign in to comment.