tc39 / proposal-seeded-random

Proposal for an options argument to be added to JS's Math.random() function, and some options to start it with.
MIT License
156 stars 6 forks source link

Thoughts on choice of algorithm #19

Open bakkot opened 1 year ago

bakkot commented 1 year ago

There's a variety of modern PRNG algorithms we could choose from, with various tradeoffs around speed, memory, predictability, complexity, miscellaneous statistical properties, and also amenability to other things you might want to do like jumping ahead.

I think the main reasonable candidates are ChaCha, PCG or a variant, and Xoshiro/Xoroshiro. Honorable mention to sfc64 and SplitMix64. Wyrand looks interesting but I think it's too new to be the default choice. Dishonorable mention to Mersenne twisters, which require an excessive amount of state with basically no compensating advantages.

Note that Xoshiro/Xoroshiro is an entire family of PRNGs, so we'd have to choose among them; some of the older ones have (what I regard as) notable weaknesses.

Of these I'd lean towards ChaCha, specifically ChaCha12 (or 8, as Go has done), which is fast enough for almost all practical purposes, has good statistical properties, is extremely difficult to predict (just as much as ChaCha20, but faster), and as a bonus supports jump-ahead (which is only relevant if we expose that capability, which we probably won't). Detailed thoughts below.


I regard being able to generate ~hundreds of megabytes per second on old hardware is probably sufficient, so among algorithms which can achieve that I'm inclined to choose based on other attributes rather than continuing to worry about performance. All mentioned algorithms are capable of that. ChaCha is the slowest, being at least an order of magnitude slower than the others.

Then the most important attribute I'd look for is being statistically well-distributed.

Beyond that I'd optimize for being at least somewhat difficult to predict. People probably shouldn't be using seeded RNGs for cryptography, but it's still a useful property in non-cryptographic applications (e.g. games).


Other bits of context you may find helpful:

tabatkins commented 1 year ago

I haven't walked thru your references yet, but this seems like incredibly useful research. Thank you so much!

Artoria2e5 commented 8 months ago

Go math/rand/v2 (https://pkg.go.dev/math/rand/v2) ended up settling with ChaCha8 as the default; it still has PCG as an option. https://github.com/golang/go/issues/61716 is the discussion, I believe. The argument is that it makes misuse-as-cryptographic-randomness less of a big arrow in the knee; I doubt that applies here given we are outputting a number.

(Although getting not just [0,1) numbers out of the bag seems useful too: maybe someone wants a well-implemented dice roll. Tangentials, tangentials...)

bakkot commented 6 months ago

More overview of Go's implementation here.