Skip to content

Conversation

@ukpratik
Copy link

Summary

This PR adds the ability to seed the random number generator used by lo functions, enabling reproducible random sequences. This is particularly useful for testing scenarios where deterministic behavior is required.

Motivation

When writing tests that involve random operations (e.g., Shuffle, RandomString,), it's often necessary to have predictable, reproducible results. Without the ability to seed the RNG, tests can be flaky or require workarounds.

Let me know if you think any changes that I should do in this PR or ay guidance, feel free to push any minor changes if required.

Use case example:

func TestMyFunction(t *testing.T) {
    lo.SetRandomSeed(42)
    defer lo.ResetRandomSeed()
    
    result := lo.Shuffle([]int{1, 2, 3, 4, 5})
    // result is now deterministic and testable
}

Changes

New Public API

Function Description
SetRandomSeed(seed int64) Sets a custom seed for reproducible random sequences. Pass negative value to reset.
ResetRandomSeed() Resets to default non-reproducible behavior. Equivalent to SetRandomSeed(-1).

Files Changed

  • rand.go - New public API functions with documentation
  • rand_test.go - Comprehensive unit tests
  • internal/xrand/ordered_go118.go - Implementation for Go < 1.22
  • internal/xrand/ordered_go122.go - Implementation for Go ≥ 1.22
  • benchmark/slice_benchmark_test.go - Added BenchmarkShuffle

Testing

✅ Unit tests added covering:

  • Reproducible RandomString with same seed
  • Reproducible Shuffle with same seed
  • Different seeds produce different results
  • Reset returns to non-reproducible behavior
  • Negative seed resets the generator
  • Sequential operations are reproducible

Benchmarks

No performance regression detected.

Benchmark comparison (10 runs each):

Benchmark Master This PR Delta
Shuffle/ints_10 53.25 ns/op 51.61 ns/op -3.1%
Shuffle/ints_100 562.3 ns/op 552.8 ns/op -1.7%
Shuffle/ints_1000 5302.7 ns/op 5244.2 ns/op -1.1%
Shuffle/strings_10 56.40 ns/op 55.48 ns/op -1.6%
Shuffle/strings_100 592.1 ns/op 582.2 ns/op -1.7%
Shuffle/strings_1000 5761.4 ns/op 5660.2 ns/op -1.8%

Memory allocations: 0 B/op (unchanged)

Full benchmark output

Benchmark report for New changes:

goos: darwin
goarch: arm64
pkg: github.com/samber/lo/benchmark
cpu: Apple M3 Pro
BenchmarkShuffle/ints_10-12             22587003                51.00 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             23390805                51.18 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             23498809                50.90 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22789028                51.59 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22319403                51.44 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             23575425                51.85 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             23278596                51.74 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22671862                52.29 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             23499038                52.15 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             23092372                51.92 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2263501               540.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2184102               545.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2216710               543.3 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2226292               539.6 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2171559               555.0 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2184602               546.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2183511               559.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2185424               599.6 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2134866               551.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2213470               546.9 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             224572              5225 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             230365              5311 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             231375              5215 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             223750              5268 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             231848              5175 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             234406              5154 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             227397              5170 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             231559              5253 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             204169              5400 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             226399              5271 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21962853                56.10 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21594774                55.41 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21210640                54.14 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21646046                55.35 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          22075224                55.24 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          20959996                55.55 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21657358                55.29 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          20714103                55.77 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21098035                55.74 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21860427                56.18 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2073867               572.6 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2070502               577.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2076459               581.9 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2069491               591.5 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2068453               584.5 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2090576               583.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2044184               574.3 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2064208               577.3 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2074052               588.5 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2045121               590.1 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          213916              5655 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          210658              5652 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          207843              5599 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          214982              5676 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          212762              5520 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          216505              5645 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          208477              5695 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          213548              5698 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          210241              5761 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          213153              5701 ns/op               0 B/op          0 allocs/op
PASS
ok      github.com/samber/lo/benchmark  86.578s

Benchmark report for Existing Code:

goos: darwin
goarch: arm64
pkg: github.com/samber/lo/benchmark
cpu: Apple M3 Pro
BenchmarkShuffle/ints_10-12             23117040                52.43 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             21367854                54.19 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22240017                52.63 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22324420                52.45 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22729209                55.41 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22683309                52.80 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             21332353                52.72 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22611945                52.63 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22675004                53.34 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_10-12             22727684                53.94 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             1710760               645.1 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2121478               568.5 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2189866               560.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2182418               556.0 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2220439               546.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2193193               552.3 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2206826               548.0 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2199376               547.4 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2122310               549.6 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_100-12             2040598               548.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             221943              5242 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             227637              5245 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             223983              5352 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             225892              5367 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             227742              5372 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             228727              5289 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             228960              5280 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             225776              5271 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             225370              5313 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/ints_1000-12             225027              5296 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          20862414                55.53 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21787744                55.69 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21429224                57.00 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21864560                56.72 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          20709277                56.75 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21250220                56.29 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21672694                57.04 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21475212                55.86 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21096628                56.44 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_10-12          21537717                56.70 ns/op            0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2044614               603.9 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2029402               589.8 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2049004               587.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2062402               590.4 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2037243               589.6 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2014292               599.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2042222               603.0 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2026527               588.2 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2031366               588.6 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_100-12          2047062               581.5 ns/op             0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          215865              5617 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          210469              5625 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          209134              5704 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          212107              5807 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          199274              6554 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          209646              5670 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          212428              5661 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          213615              5663 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          212457              5671 ns/op               0 B/op          0 allocs/op
BenchmarkShuffle/strings_1000-12          212714              5642 ns/op               0 B/op          0 allocs/op
PASS
ok      github.com/samber/lo/benchmark  87.179s

@ukpratik
Copy link
Author

@samber please check my new implementation for adding seed in xrand for test, I have detailed information for the same in the description, let me know what do you think about this.
I have also added benchmark comparisons with master code along with complete benchmark report of master and feature branch.
I would be always grateful for your guidance.

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