Update usage of random number generators #77
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Go 1.22 included a new "math/rand/v2" package (see the blog post for more details). The most exciting thing about this is a new global RNG that uses per-thread seeds and is lock-free. And it turns out that this approach is indeed much better than using a mutex with a
*rand.Rand.But for random numbers that don't need to be thread-safe, the Go 1 generator in "math/rand" is still the fastest.
So this PR removes
internal.NewLockedRand()and updates all callers to instead use the global RNG in "math/rand/v2".You can see the code I used to benchmark the RNGs in 43b8cd0. We only use a small number of operations of the RNG interface, so I wrote a benchmark for each:
Uint64andShufflemethods.Intn(calledIntNin the new "math/rand/v2" package) andFloat64.For the thread-safe benchmarks, we actually spin up multiple goroutines (based on GOMAXPROCS), so that we can also see the costs of lock contention.
For all of them, I tested the existing implementation which uses the Go 1 "math/rand" generator. And I also tested using all three of the RNGs in "math/rand/v2": the PCG and ChaCha8 algorithms as well as its global RNG (which uses the runtime's internal, lock-free RNG).
In these benchmarks, the Go 1 generator in "math/rand" maintains a reasonable lead for the non-thread-safe operations. But for thread-safety, the global RNG in "math/rand/v2" wins handily.