Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: flyingmutant/rand
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.2
Choose a base ref
...
head repository: flyingmutant/rand
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 9 commits
  • 12 files changed
  • 1 contributor

Commits on Nov 17, 2022

  1. Make staticcheck happy

    flyingmutant committed Nov 17, 2022
    Copy the full SHA
    fc2893c View commit details

Commits on Feb 8, 2023

  1. CI: test on Go 1.20

    flyingmutant committed Feb 8, 2023
    Copy the full SHA
    d64f7d2 View commit details

Commits on Aug 8, 2023

  1. CI: test on Go 1.21

    flyingmutant committed Aug 8, 2023
    Copy the full SHA
    a0b8ce0 View commit details

Commits on Aug 13, 2024

  1. Copy the full SHA
    d7e0864 View commit details
  2. CI: test on Go 1.22

    flyingmutant committed Aug 13, 2024
    Copy the full SHA
    3ac33d7 View commit details
  3. Copy the full SHA
    38fd8b8 View commit details
  4. Copy the full SHA
    6b3be63 View commit details
  5. Copy the full SHA
    42d5fb0 View commit details

Commits on Nov 5, 2024

  1. CI: test on Go 1.23

    flyingmutant committed Nov 5, 2024
    Copy the full SHA
    cc89c0d View commit details
Showing with 349 additions and 20 deletions.
  1. +4 −3 .github/workflows/ci.yml
  2. +60 −3 README.md
  3. +1 −1 global_go118.go
  4. +1 −1 global_go119.go
  5. +15 −0 global_go122.go
  6. +2 −2 global_test.go
  7. +1 −1 global_unsafe.go
  8. +18 −0 global_unsafe_go122.go
  9. +237 −0 rand_bench_std_pcg_test.go
  10. +3 −2 rand_bench_test.go
  11. +2 −2 rand_test.go
  12. +5 −5 std_rand_test.go
7 changes: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -2,14 +2,12 @@ name: CI
on:
push:
pull_request:
schedule:
- cron: "0 */13 * * *"
jobs:
ci:
name: CI
strategy:
matrix:
go: ['1.17', '1.18', '1.19']
go: ['1.18', '1.19', '1.22', '1.23']
os: ['ubuntu-latest', 'windows-latest', 'macOS-latest']
runs-on: ${{ matrix.os }}
steps:
@@ -35,5 +33,8 @@ jobs:
- name: Bench math/rand
run: go test -tags=benchstd -run=Benchmark -bench=.

- name: Bench math/rand/v2
run: go test -tags=benchstdpcg -run=Benchmark -bench=.

- name: Bench golang.org/x/exp/rand
run: go test -tags=benchx -run=Benchmark -bench=.
63 changes: 60 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -13,10 +13,56 @@ Compared to these packages, `pgregory.net/rand`:

## Benchmarks

All benchmarks were run on `Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz`,
`linux/amd64`.
Compared to [math/rand/v2](https://pkg.go.dev/math/rand/v2) (top-level functions & PCG source):

Compared to [math/rand](https://pkg.go.dev/math/rand):
`Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz`, `linux/amd64`

```
name old time/op new time/op delta
Float64-8 3.29ns ± 2% 3.55ns ±15% +7.92% (p=0.006 n=9+10)
Intn-8 3.86ns ± 1% 3.96ns ± 4% +2.58% (p=0.002 n=9+8)
Intn_Big-8 6.46ns ± 2% 7.45ns ±15% +15.35% (p=0.000 n=8+10)
Uint64-8 3.06ns ± 1% 3.20ns ± 2% +4.75% (p=0.000 n=10+8)
Rand_New 107ns ± 1% 102ns ± 1% -4.85% (p=0.000 n=9+9)
Rand_ExpFloat64 13.0ns ± 1% 8.9ns ± 3% -31.25% (p=0.000 n=9+8)
Rand_Float32 7.67ns ± 3% 3.61ns ± 2% -52.93% (p=0.000 n=9+10)
Rand_Float64 7.95ns ± 3% 4.22ns ± 2% -46.99% (p=0.000 n=10+9)
Rand_Int 6.79ns ± 1% 3.90ns ± 0% -42.54% (p=0.000 n=10+8)
Rand_Int31 6.79ns ± 1% 2.56ns ± 1% -62.30% (p=0.000 n=10+9)
Rand_Int31n 10.2ns ± 1% 4.2ns ± 1% -59.15% (p=0.000 n=9+9)
Rand_Int31n_Big 10.2ns ± 1% 4.2ns ± 1% -59.25% (p=0.000 n=9+10)
Rand_Int63 6.90ns ± 4% 3.92ns ± 1% -43.20% (p=0.000 n=9+8)
Rand_Int63n 10.3ns ± 5% 5.5ns ± 1% -46.40% (p=0.000 n=9+8)
Rand_Int63n_Big 28.8ns ± 1% 8.8ns ± 1% -69.44% (p=0.000 n=10+8)
Rand_Intn 10.2ns ± 1% 5.5ns ± 0% -46.75% (p=0.000 n=9+8)
Rand_Intn_Big 28.7ns ± 1% 8.8ns ± 1% -69.44% (p=0.000 n=9+8)
Rand_NormFloat64 14.1ns ± 2% 9.1ns ± 1% -35.19% (p=0.000 n=9+9)
Rand_Perm 951ns ± 5% 451ns ± 1% -52.60% (p=0.000 n=9+9)
Rand_Seed 0.57ns ± 3% 46.09ns ± 1% +7995.18% (p=0.000 n=10+9)
Rand_Shuffle 711ns ± 1% 412ns ± 1% -42.12% (p=0.000 n=10+8)
Rand_ShuffleOverhead 638ns ± 3% 306ns ± 1% -52.09% (p=0.000 n=9+10)
Rand_Uint32 7.12ns ±12% 2.48ns ± 1% -65.24% (p=0.000 n=10+9)
Rand_Uint64 6.86ns ± 1% 3.93ns ± 0% -42.64% (p=0.000 n=8+9)
ShuffleSlice 284ns ± 1% 278ns ± 1% -2.09% (p=0.000 n=8+8)
name old speed new speed delta
Uint64 2.62GB/s ± 1% 2.48GB/s ± 7% -5.30% (p=0.000 n=10+9)
Rand_Uint32 564MB/s ±11% 1616MB/s ± 1% +186.63% (p=0.000 n=10+9)
Rand_Uint64 1.17GB/s ± 1% 2.03GB/s ± 0% +74.32% (p=0.000 n=8+9)
name old alloc/op new alloc/op delta
Rand_New 32.0B ± 0% 48.0B ± 0% +50.00% (p=0.000 n=10+10)
Rand_Perm 416B ± 0% 416B ± 0% ~ (all equal)
name old allocs/op new allocs/op delta
Rand_New 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10)
Rand_Perm 1.00 ± 0% 1.00 ± 0% ~ (all equal)
```

<details>
<summary>Compared to <a href="https://pkg.go.dev/math/rand">math/rand</a>:</summary>

`Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz`, `linux/amd64`

```
name old time/op new time/op delta
@@ -59,10 +105,13 @@ Rand_Read 887MB/s ± 4% 2464MB/s ± 4% +177.83% (p=0.000 n=10
Rand_Uint32 511MB/s ± 3% 2306MB/s ± 7% +350.86% (p=0.000 n=10+10)
Rand_Uint64 834MB/s ± 3% 2811MB/s ± 4% +236.85% (p=0.000 n=10+10)
```
</details>

<details>
<summary>Compared to <a href="https://pkg.go.dev/golang.org/x/exp/rand">golang.org/x/exp/rand</a>:</summary>

`Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz`, `linux/amd64`

```
name old time/op new time/op delta
Float64-48 175ns ± 8% 1ns ±12% -99.65% (p=0.000 n=10+9)
@@ -120,6 +169,8 @@ Rand_Uint64 1.56GB/s ± 5% 2.81GB/s ± 4% +80.32% (p=0.000 n=10
Note that `fastrand` [does not](https://gist.github.com/flyingmutant/bf3bd489ee3c7a32f40714c11325d614)
generate good random numbers.

`Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz`, `linux/amd64`

```
name old time/op new time/op delta
Uint64-48 3.20ns ±35% 0.53ns ± 3% -83.29% (p=0.000 n=10+9)
@@ -139,6 +190,12 @@ https://gist.github.com/flyingmutant/0b380f432308beaaf09c0a038f918aa4))
quality issues, without improving the speed,
and it seems that there is no active development happening there.

### Should I use this or `math/rand/v2`?

If you are not counting nanoseconds, use `math/rand/v2`, it is a huge improvement
over nearly all aspects of `math/rand`. If you are counting nanoseconds,
`pgregory.net/rand` is still faster, without compromising quality.

### How does this thing work?

This package builds on 4 primitives: raw 64-bit generation using `sfc64` or goroutine-local
2 changes: 1 addition & 1 deletion global_go118.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//go:build !go1.19 && !unsafe
//go:build !go1.19 && !go1.22 && !unsafe

package rand

2 changes: 1 addition & 1 deletion global_go119.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//go:build go1.19 && !unsafe
//go:build go1.19 && !go1.22 && !unsafe

package rand

15 changes: 15 additions & 0 deletions global_go122.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2024 Gregory Petrosyan <gregory.petrosyan@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//go:build go1.22 && !unsafe

package rand

import "math/rand/v2"

func rand64() uint64 {
return rand.Uint64()
}
4 changes: 2 additions & 2 deletions global_test.go
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ func TestUint32n(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
n := rapid.Uint32Range(1, math.MaxUint32).Draw(t, "n").(uint32)
v := rand.Uint32n(n)
if v < 0 || v >= n {
if v >= n {
t.Fatalf("got %v outside of [0, %v)", v, n)
}
})
@@ -121,7 +121,7 @@ func TestUint64n(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
n := rapid.Uint64Range(1, math.MaxUint64).Draw(t, "n").(uint64)
v := rand.Uint64n(n)
if v < 0 || v >= n {
if v >= n {
t.Fatalf("got %v outside of [0, %v)", v, n)
}
})
2 changes: 1 addition & 1 deletion global_unsafe.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//go:build unsafe
//go:build unsafe && !go1.22

package rand

18 changes: 18 additions & 0 deletions global_unsafe_go122.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2024 Gregory Petrosyan <gregory.petrosyan@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//go:build unsafe && go1.22

package rand

import (
_ "unsafe"
)

// if you *really* want to win the benchmarks game:

//go:linkname rand64 runtime.rand
func rand64() uint64
Loading