Skip to content

Conversation

@jhump
Copy link
Member

@jhump jhump commented Apr 22, 2025

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:

  • For non-thread-safe RNGs, we only use Uint64 and Shuffle methods.
  • For thread-safe RNGs, we only use Intn (called IntN in the new "math/rand/v2" package) and Float64.
    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.

goos: darwin
goarch: arm64
pkg: github.com/bufbuild/httplb/internal
cpu: Apple M1 Max
BenchmarkRand_Uint64_rand
BenchmarkRand_Uint64_rand-10                            406894315            2.849 ns/op
BenchmarkRand_Uint64_randv2pcg
BenchmarkRand_Uint64_randv2pcg-10                       292239162            4.061 ns/op
BenchmarkRand_Uint64_randv2chacha8
BenchmarkRand_Uint64_randv2chacha8-10                   257501427            4.613 ns/op
BenchmarkRand_Uint64_randv2global
BenchmarkRand_Uint64_randv2global-10                    226841599            5.294 ns/op
BenchmarkRand_Shuffle_rand
BenchmarkRand_Shuffle_rand-10                             4805521            248.8 ns/op
BenchmarkRand_Shuffle_randv2pcg
BenchmarkRand_Shuffle_randv2pcg-10                        4451755            267.9 ns/op
BenchmarkRand_Shuffle_randv2chacha8
BenchmarkRand_Shuffle_randv2chacha8-10                    3403008            349.9 ns/op
BenchmarkRand_Shuffle_randv2global
BenchmarkRand_Shuffle_randv2global-10                     3106603            382.8 ns/op
BenchmarkRand_ConcurrentIntN_rand
BenchmarkRand_ConcurrentIntN_rand-10                      1214431            969.0 ns/op
BenchmarkRand_ConcurrentIntN_randv2pcg
BenchmarkRand_ConcurrentIntN_randv2pcg-10                 1230388            951.7 ns/op
BenchmarkRand_ConcurrentIntN_randv2chacha8
BenchmarkRand_ConcurrentIntN_randv2chacha8-10             1000000             1027 ns/op
BenchmarkRand_ConcurrentIntN_randv2global
BenchmarkRand_ConcurrentIntN_randv2global-10             39565887            88.69 ns/op
BenchmarkRand_ConcurrentFloat64_rand
BenchmarkRand_ConcurrentFloat64_rand-10                   1270753            947.7 ns/op
BenchmarkRand_ConcurrentFloat64_randv2pcg
BenchmarkRand_ConcurrentFloat64_randv2pcg-10              1279284            928.6 ns/op
BenchmarkRand_ConcurrentFloat64_randv2chacha8
BenchmarkRand_ConcurrentFloat64_randv2chacha8-10          1272981            948.7 ns/op
BenchmarkRand_ConcurrentFloat64_randv2global
BenchmarkRand_ConcurrentFloat64_randv2global-10         148186993            7.944 ns/op

@jhump jhump requested a review from a user April 22, 2025 19:37
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

@jhump jhump merged commit b069868 into main Apr 23, 2025
5 checks passed
@jhump jhump deleted the jh/rand-benchmarks branch April 23, 2025 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants