Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: common/data/rand/mathrand/mathrand_test.go

Issue 2588213002: Use global rand.Rand instance in mathrand. (Closed)
Patch Set: Better comment. Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/data/rand/mathrand/mathrand.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package mathrand 5 package mathrand
6 6
7 import ( 7 import (
8 "math" 8 "math"
9 "math/rand" 9 "math/rand"
10 "testing" 10 "testing"
11 11
12 . "github.com/smartystreets/goconvey/convey" 12 . "github.com/smartystreets/goconvey/convey"
13 "golang.org/x/net/context" 13 "golang.org/x/net/context"
14 ) 14 )
15 15
16 func Test(t *testing.T) { 16 func Test(t *testing.T) {
17 t.Parallel() 17 t.Parallel()
18 18
19 Convey("test mathrand", t, func() { 19 Convey("test mathrand", t, func() {
20 c := context.Background() 20 c := context.Background()
21 21
22 Convey("unset", func() { 22 Convey("unset", func() {
23 // Just ensure doesn't crash. 23 // Just ensure doesn't crash.
24 So(Get(c).Int()+1 > 0, ShouldBeTrue) 24 So(Get(c).Int()+1 > 0, ShouldBeTrue)
25 So(WithGoRand(c, func(r *rand.Rand) error {
26 So(r.Int(), ShouldBeGreaterThanOrEqualTo, 0)
27 return nil
28 }), ShouldBeNil)
25 }) 29 })
26 30
27 Convey("set persistance", func() { 31 Convey("set persistance", func() {
28 c = Set(c, rand.New(rand.NewSource(12345))) 32 c = Set(c, rand.New(rand.NewSource(12345)))
29 r := rand.New(rand.NewSource(12345)) 33 r := rand.New(rand.NewSource(12345))
30 So(Get(c).Int(), ShouldEqual, r.Int()) 34 So(Get(c).Int(), ShouldEqual, r.Int())
31 So(Get(c).Int(), ShouldEqual, r.Int()) 35 So(Get(c).Int(), ShouldEqual, r.Int())
32 }) 36 })
33 37
34 Convey("nil set", func() { 38 Convey("nil set", func() {
35 c = Set(c, nil) 39 c = Set(c, nil)
36 // Just ensure doesn't crash. 40 // Just ensure doesn't crash.
37 So(Get(c).Int()+1 > 0, ShouldBeTrue) 41 So(Get(c).Int()+1 > 0, ShouldBeTrue)
38 }) 42 })
39 }) 43 })
40 44
41 Convey("fairness of uninitialized source", t, func() { 45 Convey("fairness of uninitialized source", t, func() {
42 // We do some ugly stuff in Get(...) if context doesn't have mat h.Rand set, 46 // We do some ugly stuff in Get(...) if context doesn't have mat h.Rand set,
43 // check that the produced RNG sequence matches the uniform dist ribution 47 // check that the produced RNG sequence matches the uniform dist ribution
44 // at least at first two moments. 48 // at least at first two moments.
45 ctx := context.Background() 49 ctx := context.Background()
46 » » mean, dev := calcStats(10000, func() float64 { 50 » » mean, dev := calcStats(20000, func() float64 {
47 return Get(ctx).Float64() 51 return Get(ctx).Float64()
48 }) 52 })
49 53
50 // For ideal uniform [0, 1) distribution it should be: 54 // For ideal uniform [0, 1) distribution it should be:
51 // Average: 0.500000 55 // Average: 0.500000
52 // Standard deviation: 0.288675 56 // Standard deviation: 0.288675
53 So(mean, ShouldBeBetween, 0.495, 0.505) 57 So(mean, ShouldBeBetween, 0.495, 0.505)
54 So(dev, ShouldBeBetween, 0.284, 0.29) 58 So(dev, ShouldBeBetween, 0.284, 0.29)
55 }) 59 })
56 } 60 }
57 61
62 func testConcurrentAccess(t *testing.T, r *rand.Rand) {
63 const goroutines = 16
64 const rounds = 1024
65
66 Convey(`Concurrent access does not produce a race or deadlock.`, func() {
67 c := context.Background()
68 if r != nil {
69 c = Set(c, r)
70 }
71
72 startC := make(chan struct{})
73 doneC := make(chan struct{}, goroutines)
74 for g := 0; g < goroutines; g++ {
75 go func() {
76 defer func() {
77 doneC <- struct{}{}
78 }()
79
80 <-startC
81 for i := 0; i < rounds; i++ {
82 Int(c)
83 }
84 }()
85 }
86
87 close(startC)
88 for reap := 0; reap < goroutines; reap++ {
89 <-doneC
90 }
91 })
92
93 }
94
95 // TestConcurrentGlobalAccess is intentionally NOT Parallel, since we want to
96 // have exclusive access to the global instance.
97 func TestConcurrentGlobalAccess(t *testing.T) {
98 Convey(`Testing concurrent global access`, t, func() {
99 testConcurrentAccess(t, nil)
100 })
101 }
102
103 func TestConcurrentAccess(t *testing.T) {
104 t.Parallel()
105
106 Convey(`Testing concurrent non-global access`, t, func() {
107 testConcurrentAccess(t, newRand())
108 })
109 }
110
58 func calcStats(n int, gen func() float64) (avg float64, std float64) { 111 func calcStats(n int, gen func() float64) (avg float64, std float64) {
59 var m1 float64 112 var m1 float64
60 var m2 float64 113 var m2 float64
61 114
62 for i := 0; i < n; i++ { 115 for i := 0; i < n; i++ {
63 x := gen() 116 x := gen()
64 m1 += x 117 m1 += x
65 m2 += x * x 118 m2 += x * x
66 } 119 }
67 120
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 ctx := context.Background() 156 ctx := context.Background()
104 WithGoRand(ctx, func(r *rand.Rand) error { 157 WithGoRand(ctx, func(r *rand.Rand) error {
105 ctx = Set(ctx, r) 158 ctx = Set(ctx, r)
106 calcStats(b.N, func() float64 { 159 calcStats(b.N, func() float64 {
107 return Float64(ctx) 160 return Float64(ctx)
108 }) 161 })
109 return nil 162 return nil
110 }) 163 })
111 } 164 }
112 165
113 // BenchmarkStdlibDefaultSource-8 » 50000000» 32.0 ns/ op 166 func BenchmarkGlobalSource(b *testing.B) {
114 // BenchmarkOurDefaultSourceViaCtx-8 » 200000» 10893 ns/ op 167 » r, _ := getGlobalRand()
115 // BenchmarkOurDefaultSourceViaFunc-8 » 30000000» 38.7 ns/ op 168 » calcStats(b.N, func() float64 {
116 // BenchmarkOurInitializedSourceViaCtx-8 » 50000000» 30.2 ns/ op 169 » » return r.Float64()
117 // BenchmarkOurInitializedSourceViaFunc-8 » 50000000» 29.1 ns/ op 170 » })
171 }
172
173 // BenchmarkStdlibDefaultSource-32 30000000 35.6 ns/op
174 // BenchmarkOurDefaultSourceViaCtx-32 20000000 77.8 ns/op
Vadim Sh. 2016/12/20 02:31:56 awesome!
dnj 2016/12/20 02:36:06 To be fair it's b/c I'm not doing an allocation pe
175 // BenchmarkOurDefaultSourceViaFunc-32 20000000 78.6 ns/op
176 // BenchmarkOurInitializedSourceViaCtx-32 20000000 86.8 ns/op
177 // BenchmarkOurInitializedSourceViaFunc-32 20000000 81.9 ns/op
178 // BenchmarkGlobalSource-32 30000000 43.8 ns/op
OLDNEW
« no previous file with comments | « common/data/rand/mathrand/mathrand.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698