I realize the BIF option may not be preferred, but out of curiosity I put together a proof-of-concept similar to unique_integer
where the random state is stored on each scheduler’s ErtsSchedulerData
. There’s also a global state which jumps for each scheduler’s initial state so each scheduler has its own non-overlapping subsequence.
It uses the Xoroshiro116+ code in rand.erl
as well as SplitMix64 for establishing the initial global state on boot.
Here’s the code (based on master at 86fc3db): WIP - erlang:random_integer/0,1 BIF · potatosalad/otp@e3427a8 · GitHub
Single process test:
erlperf -c 1 'erlang:random_integer(1000).' 'erlang:phash2(erlang:unique_integer(), 1000).' 'rand:uniform(1000).'
Code || QPS Rel
erlang:random_integer(1000). 1 33956 Ki 100%
erlang:phash2(erlang:unique_integer(), 1000). 1 22099 Ki 65%
rand:uniform(1000). 1 10102 Ki 29%
64 process test (matches the number of online schedulers):
erlperf -c 64 'erlang:random_integer(1000).' 'erlang:phash2(erlang:unique_integer(), 1000).' 'rand:uniform(1000).'
Code || QPS Rel
erlang:random_integer(1000). 64 37147 Ki 100%
erlang:phash2(erlang:unique_integer(), 1000). 64 27644 Ki 74%
rand:uniform(1000). 64 14981 Ki 40%