Repository navigation
Performance Random Performance
Auto-generated via RandomPerformanceTests.Benchmark. Run the test to refresh these summary and detail tables.
State repair for a generator restored from JSON or protobuf happens in its constructor or the shared after-deserialization callback. This includes each generator's state, the shared bit/byte reservoirs and GUID scratch buffer. Repair is not repeated in a draw method, so malformed/default serialized state is repaired before the first draw without adding a guard to every later draw. PhotonSpin's one-time warmup priming also happens there, leaving only its block-boundary check in the draw path.
For statistical batteries, the repository's
Generator~/WallstopStudios.UnityHelpers.RandomQuality host emits a reproducible little-endian byte
stream from an explicit generator, GUID seed and byte count. Long PractRand/TestU01 runs belong in
scheduled reporting with pinned tools and expected weak-generator failures; they are not suitable as
nondeterministic pull-request gates.
The
NextUlong,NextLongandNextDoublecolumns below predate the one-advance-per-64-bit-draw change toBlastCircuitRandom,RomuDuo,SplitMix64,WyRandomandXoshiro256StarStar, which is measured at 2.49x on Unity 6000.4.6f1 (Mono). They refresh the next timeRandomPerformanceTests.Benchmarkruns.
| Random | NextUint (ops/s) | Speed | Quality | Notes |
|---|---|---|---|---|
| LinearCongruentialGenerator | 1,323,700,000 | Fastest | Poor | Numerical 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. |
| WaveSplatRandom | 1,283,400,000 | Fastest | Experimental | Single-word chaotic generator; author notes period 2^64 but provides no formal test results—treat as experimental. |
| BlastCircuitRandom | 1,054,900,000 | Very Fast | Good | Chaotic ARX mixer rather than a proven statistically optimal generator. Verified here: PractRand 0.95 clean through 8GB, the depth at which SystemRandom fails. |
| SplitMix64 | 1,052,300,000 | Very Fast | Very Good | Well-known SplitMix64 mixer; passes TestU01 BigCrush and PractRand up to large data sizes in literature. Vigna 2014 |
| FlurryBurstRandom | 923,200,000 | Fast | Excellent | Six-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. |
| PcgRandom | 897,900,000 | Fast | Excellent | PCG XSH RR 64/32 variant; passes TestU01 BigCrush and PractRand in published results. O'Neill 2014 |
| XoroShiroRandom | 754,700,000 | Fast | Good | xoroshiro128+, 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 |
| IllusionFlow | 754,500,000 | Fast | Excellent | Five-word rotate/xor/add generator driven by a 32-bit Weyl counter, and the generator PRNG.Instance returns. 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. |
| RomuDuo | 750,100,000 | Fast | Good | ROMU multiplier with a modified duo update; returns the low 32 bits of the 64-bit product. Not the published romuDuo or romuDuoJr, so their measured results do not transfer. Overton 2020 |
| StormDropRandom | 705,200,000 | Moderate | Excellent | Large-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. |
| XorShiftRandom | 602,100,000 | Moderate | Fair | Classic 32-bit xorshift; known to fail portions of TestU01 and PractRand, acceptable for lightweight effects only. Marsaglia 2003 |
| WyRandom | 440,500,000 | Slow | Very Good | Wyhash-based generator; published testing shows it clears BigCrush/PractRand with wide seed coverage. Wang Yi 2019 |
| SquirrelRandom | 414,000,000 | Slow | Fair | Hash-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 |
| PhotonSpinRandom | 261,100,000 | Very Slow | Excellent | SHISHUA-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. |
| UnityRandom | 87,600,000 | Very Slow | Fair | Mirrors UnityEngine.Random, documented by Unity as Xorshift 128; suitable for legacy compatibility but not high-stakes simulation. UnityEngine.Random |
| SystemRandom | 64,700,000 | Very Slow | Poor | Reimplements 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 |
| DotNetRandom | 55,900,000 | Very Slow | Poor | Wraps 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 |
| Random | NextBool | Next | NextUint | NextFloat | NextDouble | NextUint (Range) | NextInt (Range) |
|---|---|---|---|---|---|---|---|
| LinearCongruentialGenerator | 785,200,000 | 538,800,000 | 1,323,700,000 | 184,300,000 | 296,300,000 | 582,900,000 | 498,700,000 |
| WaveSplatRandom | 787,300,000 | 528,500,000 | 1,283,400,000 | 184,300,000 | 297,900,000 | 529,000,000 | 458,200,000 |
| BlastCircuitRandom | 788,200,000 | 537,400,000 | 1,054,900,000 | 183,800,000 | 293,200,000 | 479,700,000 | 421,200,000 |
| SplitMix64 | 795,900,000 | 537,200,000 | 1,052,300,000 | 184,400,000 | 297,700,000 | 482,500,000 | 439,100,000 |
| FlurryBurstRandom | 767,800,000 | 526,500,000 | 923,200,000 | 182,300,000 | 293,100,000 | 449,800,000 | 404,100,000 |
| PcgRandom | 249,800,000 | 527,300,000 | 897,900,000 | 181,000,000 | 274,700,000 | 447,700,000 | 405,000,000 |
| XoroShiroRandom | 761,000,000 | 359,000,000 | 754,700,000 | 157,900,000 | 192,400,000 | 422,100,000 | 376,900,000 |
| IllusionFlow | 779,300,000 | 529,200,000 | 754,500,000 | 183,000,000 | 281,600,000 | 439,200,000 | 390,000,000 |
| RomuDuo | 784,600,000 | 359,400,000 | 750,100,000 | 156,100,000 | 188,700,000 | 437,700,000 | 384,600,000 |
| StormDropRandom | 776,600,000 | 523,600,000 | 705,200,000 | 180,600,000 | 252,400,000 | 393,500,000 | 356,700,000 |
| XorShiftRandom | 783,300,000 | 534,100,000 | 602,100,000 | 184,100,000 | 283,200,000 | 474,500,000 | 383,500,000 |
| WyRandom | 749,500,000 | 363,000,000 | 440,500,000 | 159,000,000 | 185,300,000 | 290,000,000 | 277,800,000 |
| SquirrelRandom | 756,300,000 | 382,700,000 | 414,000,000 | 158,800,000 | 197,800,000 | 355,500,000 | 309,500,000 |
| PhotonSpinRandom | 713,300,000 | 220,800,000 | 261,100,000 | 119,900,000 | 115,800,000 | 217,600,000 | 214,200,000 |
| UnityRandom | 628,900,000 | 76,700,000 | 87,600,000 | 59,700,000 | 38,800,000 | 81,800,000 | 81,900,000 |
| SystemRandom | 146,200,000 | 145,700,000 | 64,700,000 | 131,300,000 | 138,600,000 | 58,700,000 | 57,800,000 |
| DotNetRandom | 544,600,000 | 53,100,000 | 55,900,000 | 44,700,000 | 26,700,000 | 53,400,000 | 51,700,000 |
The tables above are rewritten only by a benchmark run, so a generator added since the last one is
absent until the .github/workflows/unity-benchmarks.yml workflow next runs.
Absence here says nothing about quality: statistical standing is measured separately, by the
bit-plane linearity gate on every pull request and by the scheduled PractRand battery. See
Random Generators for the current ratings.
The battery runs both stream widths. NextUlong is no longer NextUint rearranged: five
generators answer a 64-bit draw from one raw word, so half of it reaches a caller only through
NextDouble, NextLong and NextUlong(max) and appears in no 32-bit draw. Even the generators
that do build NextUlong from two NextUint draws pack them high-word-first and write
little-endian, so their 64-bit stream is the 32-bit one with each adjacent word pair swapped.
SystemRandom is the proof that this is not a redundant measurement: it fails the 32-bit battery at
exactly 8GB and is clean through 8GB at 64-bit. Every "clean through 8GB" above is the 32-bit
figure; the 64-bit outcomes are recorded per generator in
scripts/random-quality/expected-outcomes.json.
📦 Unity Helpers | 📖 Documentation | 🐛 Issues | 📜 MIT License
- Inspector Button
- Inspector Conditional Display
- Inspector Grouping Attributes
- Inspector Inline Editor
- Inspector Overview
- Inspector Selection Attributes
- Inspector Settings
- Inspector Validation Attributes
- Utility Components
- Visual Components
- Data Structures
- Helper Utilities
- Math And Extensions
- Pooling Guide
- Random Generators
- Reflection Helpers
- Singletons
- Asset Change Detection
- Asset Validation
- Authored Asset Validation
- Editor Tools Guide
- Failed Tests Exporter
- Sprite Animation Motion
- Test Run Reporter
- Unity Method Analyzer
- Ai Model Backends
- Bundled Assembly Conflicts
- Mcp Ecosystem
- Mcp Local Setup
- Odin Migration Guide
- Unity Devcontainer Licensing