Commit bd644b9 1 parent 0422e81 commit bd644b9 Copy full SHA for bd644b9
File tree 2 files changed +33
-10
lines changed
2 files changed +33
-10
lines changed Original file line number Diff line number Diff line change 1
1
package route
2
2
3
3
import (
4
+ "math/rand"
4
5
"sync/atomic"
5
- "time"
6
6
)
7
7
8
8
// picker selects a target from a list of targets.
@@ -27,17 +27,13 @@ func rrPicker(r *Route) *Target {
27
27
return u
28
28
}
29
29
30
- // stubbed out for testing
31
- // we implement the randIntN function using the nanosecond time counter
32
- // since it is 15x faster than using the pseudo random number generator
33
- // (12 ns vs 190 ns) Most HW does not seem to provide clocks with ns
34
- // resolution but seem to be good enough for µs resolution. Since
35
- // requests are usually handled within several ms we should have enough
36
- // variation. Within 1 ms we have 1000 µs to distribute among a smaller
37
- // set of entities (<< 100)
30
+ // as it turns out, math/rand's Intn is now way faster (4x) than the previous implementation using
31
+ // time.UnixNano(). As a bonus, this actually works properly on 32 bit platforms.
38
32
var randIntn = func (n int ) int {
39
33
if n == 0 {
40
34
return 0
41
35
}
42
- return int ( time . Now (). UnixNano () / int64 ( time . Microsecond )) % n
36
+ return rand . Intn ( n )
43
37
}
38
+
39
+
Original file line number Diff line number Diff line change 4
4
"net/url"
5
5
"reflect"
6
6
"testing"
7
+ "time"
7
8
)
8
9
9
10
var (
@@ -56,3 +57,29 @@ func TestRRPicker(t *testing.T) {
56
57
}
57
58
}
58
59
}
60
+
61
+ // This is an improved version of the previous UnixNano implementation
62
+ // This one does not overflow on 32 bit platforms, it casts to int after
63
+ // doing mod. doing it before caused overflows.
64
+ var oldRandInt = func (n int ) int {
65
+ if n == 0 {
66
+ return 0
67
+ }
68
+ return int (time .Now ().UnixNano ()/ int64 (time .Microsecond ) % int64 (n ))
69
+ }
70
+
71
+ var result int // prevent compiler optimization
72
+ func BenchmarkOldRandIntn (b * testing.B ) {
73
+ var r int // more shields against compiler optimization
74
+ for i := 0 ; i < b .N ; i ++ {
75
+ r = oldRandInt (i )
76
+ }
77
+ result = r
78
+ }
79
+ func BenchmarkMathRandIntn (b * testing.B ) {
80
+ var r int // more shields against compiler optimization
81
+ for i := 0 ; i < b .N ; i ++ {
82
+ r = randIntn (i )
83
+ }
84
+ result = r
85
+ }
You can’t perform that action at this time.
0 commit comments