Skip to content

Random Number Generator Performance Benchmarks

Use the tables below as historical measurements, then profile the random operations your game actually calls. Throughput, statistical quality and replay compatibility answer different questions. A fast raw integer draw does not establish the cost or behavior of a bounded or Gaussian sample.

How the Speed column is measured

The ops/s columns measure generators sequentially on one machine. Machine load can change between measurements, so use them as local throughput observations rather than a universal ranking.

The Speed column uses paired comparisons against IllusionFlow, with alternating measurement order and repeated readings. When readings vary by more than 3%, the benchmark falls back to an unpaired measurement and reports that limitation. Device, backend and workload differences still matter even for a stable paired result.

Statistical quality

PractRand tests a byte stream up to a reported depth, such as 8 GB. TestU01 SmallCrush runs a smaller fixed set of statistical tests. Passing one does not imply passing the other, and neither proves suitability for every use. The descriptions distinguish observed outcomes from unmeasured claims. In particular, Sfc64Random has no recorded PractRand depth at either stream width; its deterministic bit-plane checks do not supply that result.

Isolated SmallCrush p-values can occur by chance. The historical comparison used a failure threshold below 1e-10; weaker deviations were recorded separately. Do not interpret a single passing statistical run as a cryptographic guarantee.

Whole-inventory SmallCrush, 2026-08-26, seed 00010203-0405-0607-0809-0a0b0c0d0e0f, 908 MB and 6.3 s of CPU per generator:

  • Every generator rated Good or better passed.
  • Four recorded-weak generators failed decisively, most of their statistics at eps: LinearCongruentialGenerator, WDoomRandom, WaveSplatRandom, XorShiftRandom.
  • Three recorded-weak generators passed: DotNetRandom, SquirrelRandom, SystemRandom. SmallCrush is the shallower instrument, so that is inconclusive rather than a contradiction of their rating.

The NextUlong, NextLong and NextDouble columns below predate the one-advance-per-64-bit-draw change to BlastCircuitRandom, RomuDuo, SplitMix64, WyRandom and Xoshiro256StarStar, which is measured at 2.49x on Unity 6000.4.6f1 (Mono). They refresh the next time RandomPerformanceTests.Benchmark runs.

Summary (fastest first)

Random NextUint (ops/s) Speed Quality Notes
LinearCongruentialGenerator1,238,600,000FastestPoorNumerical Recipes 'quick and dirty' LCG (a=1664525, c=1013904223, m=2^32) returning the raw state, so bit k has period only 2^(k+1) -- measured linear complexity of bit k is 2^k+1, and bit 0 simply alternates. Cosmetic use only.
WaveSplatRandom1,126,300,000Very FastExperimentalSingle-word chaotic generator; author notes period 2^64 but provides no formal test results—treat as experimental.
XoroShiroRandom1,024,600,000Very FastGoodxoroshiro128+, returning the high 32 bits -- the half its authors recommend. The discarded low half is linear (bit 0 has linear complexity exactly 128); no output bit of the returned half is. A 64-bit draw costs two state advances, because a + scrambler has no strong 64-bit word to return. Blackman & Vigna 2018
BlastCircuitRandom1,023,900,000Very FastGoodChaotic ARX mixer rather than a proven statistically optimal generator. Verified here: PractRand 0.95 clean through 8GB, the depth at which SystemRandom fails.
RomuDuo943,800,000Very FastGoodPublished romuDuo: the ROMU multiplier with the ROTL(y,36) + ROTL(y,15) - x update. NextUint returns the low 32 bits of the 64-bit word. Overton 2020
Sfc64Random941,700,000Very FastVery Goodsfc64 (Small Fast Chaotic): three 64-bit words plus a draw counter, seeded by the canonical twelve-draw warm-up. NextUint returns the upper half of the output word, where every mixed bit arrives. O'Neill 2018 (Doty-Humphrey's SFC)
SplitMix64912,200,000FastVery GoodSplitMix64 mixer; Vigna reports passing TestU01 BigCrush. Vigna 2015
FlurryBurstRandom905,800,000FastExcellentSix-word ARX-style generator tuned for all-around use. Verified here: PractRand 0.95 clean through 8GB, the depth at which SystemRandom fails. The author reports TestU01 BigCrush passes; that run cannot be checked -- the upstream repository is offline.
PcgRandom896,800,000FastExcellentPCG XSH RR 64/32 variant; passes TestU01 BigCrush and PractRand in published results. O'Neill 2014
IllusionFlow871,600,000FastExcellentFive-word rotate/xor/add generator driven by a 32-bit Weyl counter. Verified here: PractRand 0.95 clean through 8GB, the depth at which SystemRandom fails. The author reports 64GB; that run cannot be checked -- the upstream repository is offline.
XorShiftRandom862,300,000FastFairClassic 32-bit xorshift; known to fail portions of TestU01 and PractRand, acceptable for lightweight effects only. Marsaglia 2003
StormDropRandom696,800,000FastExcellentLarge-state ARX generator over a 1024-word (4 KB) ring buffer with two 32-bit control words. Verified here: PractRand 0.95 clean through 8GB, the depth at which SystemRandom fails. The author's own results cannot be checked -- the upstream repository is offline.
Xoshiro256StarStar606,600,000ModerateExcellentxoshiro256** 1.0; the ** scrambler leaves no weak bit, and the native 64-bit word means NextUlong costs one state advance instead of the two every other 64-bit generator here needs. Blackman & Vigna 2018
Xoshiro128StarStar599,100,000ModerateExcellentxoshiro128** 1.1; the ** scrambler leaves no weak bit, so NextBool and low-bit masks are as strong as the full word. Native 32-bit output, so NextUint discards nothing. Blackman & Vigna 2018
WyRandom441,400,000ModerateVery GoodWyhash v1 .NET port; raw 64-bit draws match cocowalla's WyRng for the same ulong seed. cocowalla 2019 (Wang Yi's wyrand)
SquirrelRandom406,400,000SlowFairHash-based generator built on Squirrel3. Measured: fails PractRand 0.95 FPF-14+6/16 at 1GB, reproducibly across four seeds. Good equidistribution for the table lookups it was designed for; not a general-purpose stream. Squirrel Eiserloh
PhotonSpinRandom254,100,000SlowExcellentSHISHUA-inspired generator. Verified here: PractRand 0.95 clean through 8GB, the depth at which SystemRandom fails. The author reports 128GB; that run cannot be checked -- the upstream repository is offline.
WDoomRandom200,100,000Very SlowPoorIndex-into-array generator over a fixed 1024-entry table of 32-bit values. One entry serves one NextUint, so the period is exactly 1024 draws. Deterministic by design, not statistically random.
UnityRandom131,000,000Very SlowFairMirrors UnityEngine.Random, documented by Unity as Xorshift 128; suitable for legacy compatibility but not high-stakes simulation. UnityEngine.Random
SystemRandom63,200,000Very SlowPoorReimplements the classic .NET System.Random algorithm (Knuth subtractive lagged-Fibonacci, mod 2^31-1) so its sequence is serializable and stable across runtimes. Fails modern statistical batteries. System.Random considered harmful
DotNetRandom58,700,000Very SlowPoorWraps System.Random, which on Mono and for seeded .NET Core is Knuth's subtractive lagged-Fibonacci generator (mod 2^31-1), not an LCG. The sequence is runtime-dependent, so do not rely on it for cross-platform determinism. System.Random considered harmful

Detailed Metrics

Random NextBool Next NextUint NextFloat NextDouble NextUint (Range) NextInt (Range)
LinearCongruentialGenerator777,900,000676,100,0001,238,600,000171,900,000369,900,000492,500,000391,400,000
WaveSplatRandom773,400,000591,500,0001,126,300,000173,600,000380,000,000438,000,000399,500,000
XoroShiroRandom767,000,000552,600,0001,024,600,000166,900,000347,400,000423,800,000363,900,000
BlastCircuitRandom750,900,000525,800,0001,023,900,000166,700,000580,000,000410,100,000339,900,000
RomuDuo778,700,000554,300,000943,800,000169,000,000580,800,000428,300,000389,100,000
Sfc64Random742,800,000537,200,000941,700,000164,600,000566,700,000392,300,000352,200,000
SplitMix64768,600,000571,400,000912,200,000164,300,000561,600,000411,700,000379,600,000
FlurryBurstRandom749,300,000546,800,000905,800,000172,000,000293,200,000386,100,000340,300,000
PcgRandom754,600,000545,900,000896,800,000165,600,000321,100,000376,200,000361,000,000
IllusionFlow775,800,000521,800,000871,600,000165,700,000296,400,000371,900,000338,100,000
XorShiftRandom756,400,000620,200,000862,300,000173,200,000364,300,000424,800,000365,900,000
StormDropRandom744,600,000458,000,000696,800,000166,600,000253,600,000341,900,000309,800,000
Xoshiro256StarStar738,900,000461,900,000606,600,000175,100,000539,700,000354,900,000320,200,000
Xoshiro128StarStar760,000,000470,300,000599,100,000166,300,000264,900,000359,300,000324,800,000
WyRandom744,200,000338,400,000441,400,000157,900,000360,200,000264,600,000228,100,000
SquirrelRandom739,500,000391,400,000406,400,000162,400,000191,100,000302,800,000288,600,000
PhotonSpinRandom688,600,000228,800,000254,100,000116,300,000112,800,000201,700,000184,000,000
WDoomRandom698,400,000210,400,000200,100,000138,200,000105,900,000207,700,000200,600,000
UnityRandom686,200,000122,000,000131,000,00078,500,00060,000,000117,800,000119,300,000
SystemRandom138,300,000142,900,00063,200,000128,400,000131,100,00057,800,00056,800,000
DotNetRandom531,500,00054,800,00058,700,00044,800,00027,400,00053,100,00044,600,000

Choose a generator for your game

Use the tables to compare the measured operations, then read the random generator guide for the current generator choices and APIs. A generator added after the recorded benchmark run may be absent from these tables. Absence is not a quality or speed rating.

The NextUint column measures raw 32-bit draws. Bounded integers, floating-point transforms, weighted selection and Gaussian draws do different work. Compare the operation your game uses, and profile it on your target device and scripting backend before changing generators for speed.

Statistical quality is separate from throughput. A clean finite test stream is not a guarantee for every seed or workload. The quality descriptions above refer to the tested 32-bit streams; a 64-bit draw can use a different part or ordering of a generator's state. These generators are not cryptographic random sources.

Raw-stream compatibility

A raw stream is the sequence returned by unbounded NextUint() or NextUlong() calls. It is separate from bounded sampling, which can consume more than one raw draw when rejecting a value. Changing the bounds, operation order or failure policy can therefore change later results even when the underlying raw stream stays the same.

For deterministic gameplay, record the generator type, seed or saved state, package version and call order. Save a snapshot when you need to resume partway through a stream: a seed alone does not include cached Gaussian, bit or byte state. See saving and restoring random state for the snapshot APIs.

Generator family Replay consideration
Package-managed generators Keep the generator and saved state format consistent; check retained replays when upgrading.
NativePcgRandom Value copies preserve its state, including partially consumed bit reservoirs; it has no RandomState or protobuf API.
UnityRandom Follows the running Unity engine; do not assume identical engine streams or snapshot payloads across Unity versions.
DotNetRandom Wraps System.Random; its sequence depends on the runtime.
WDoomRandom Deliberately repeats a fixed table; use only when that deterministic behavior is intended.

Raw-stream compatibility does not establish statistical quality, throughput or allocation cost. Validate each property that your game depends on, including mixed sampling calls and retained saves, on the backends you ship.

Refreshing these numbers

The package publishes refreshed tables after its benchmark workflow completes. To measure your own project, run RandomPerformanceTests.Benchmark in Unity's Test Runner with the package tests enabled. Keep the Unity version, backend and device with your results so later comparisons use the same environment.