Open svaarala opened 8 years ago
My instinct is that it's probably not worth it to provide a method for manual seeding as such to the application; by the time an application needs to do this it'd make more sense just to swap out the whole RNG, which is already possible now.
What might be worth pursuing, however, is to expose the xoroshiro128+ state through the API. Then an application can save and restore the state (potentially useful for repeatable tests), or even modify it directly for manual mixing--XOR'ing in values every once in a while, for example. One roadblock for this is that xoroshiro128+ isn't used on all targets yet.
I wouldn't want to expose the specific algorithm via the API. It's not impossible that it would change again later on.
@fatcerberus By the way, note that the ability to save/restore the internal PRNG state does not mean Math.random()
output could be in effect rewound/restarted. The reason for this is that the internal PRNG is also used for internal purposes, currently for Array.prototype.sort()
random pivot selection. So if any sort() calls are done, that will also affect the Math.random()
sequence. The random state is also shared across all threads in the same Duktape heap which makes the individual Math.random()
sequences in each thread potentially unpredictable. This is quite intentional right now, and it's quite likely some other internals will need access to randomization at some point.
So applications desiring a predictable, controllable Math.random()
stream should replace Math.random()
or use a separate random number binding entirely, and not just replace the internal provider.
In this sense the Ecmascript randomization API is quite a barebones one. It'd be a pretty useful API to be able to create multiple PRNG sources and control who draws data from them. But that's not the case for the default built-in. On the other hand one strength of the Ecmascript built-in bindings is that they're simple and there's very little "provider factory" thinking :)
I actually implemented such a system in minisphere where games can create individual RNG streams and manage their states independently:
https://github.com/fatcerberus/minisphere/blob/master/docs/sphere2-api.txt#L243-L288
Looks useful, that's something I'd also prefer if my application required a controlled PRNG source. It's somewhat unfortunately that Duktape can't easily help with that, at least without introducing custom Ecmascript or C bindings :-/.
I generally use current time and process ID for seeding RNGs, for my C projects.
Current implementation is xoroshiro128+ with seed derived from
Date.now()
andduk_heap
pointer, premixed using SplitMix64. The main shortcoming of this setup is that the seed is very similar when creating multiple Duktape heaps. There's also no way to explicitly provide a seed from user code (although the entire PRNG provider can be changed).Also if two Duktape heaps are created at exactly the same moment and they get the same
duk_heap
pointer (for example because they are two separate processes with the same virtual address layout) the same PRNG sequence can be generated.There's some discussion of various issues and alternatives in #970.