]> Cypherpunks repositories - gostls13.git/commitdiff
math/rand: devirtualize interface in lockedSource
authorCarlo Alberto Ferraris <cafxx@strayorange.com>
Fri, 23 Aug 2019 23:59:01 +0000 (08:59 +0900)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Sun, 29 Sep 2019 14:27:05 +0000 (14:27 +0000)
Avoid interface calls, enable inlining, and store the rngSource close to the
Mutex to exploit better memory locality.

Also add a benchmark to properly measure the threadsafe nature of globalRand.

On a linux/amd64 VM:

name                       old time/op  new time/op  delta
Int63Threadsafe-4          36.4ns ±12%  20.6ns ±11%  -43.52%  (p=0.000 n=30+30)
Int63ThreadsafeParallel-4  79.3ns ± 5%  56.5ns ± 5%  -28.69%  (p=0.000 n=29+30)

Change-Id: I6ab912c1a1e9afc7bacd8e72c82d4d50d546a510
Reviewed-on: https://go-review.googlesource.com/c/go/+/191538
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/inl_test.go
src/math/rand/rand.go
src/math/rand/rand_test.go

index a0f56e776bd884f29fd2f1966f98ed1168b1f48f..77c398af826903c4315ff145f84d7e946943bfb5 100644 (file)
@@ -148,6 +148,10 @@ func TestIntendedInlining(t *testing.T) {
                        "addVW",
                        "subVW",
                },
+               "math/rand": {
+                       "(*rngSource).Int63",
+                       "(*rngSource).Uint64",
+               },
        }
 
        if runtime.GOARCH != "386" && runtime.GOARCH != "mips64" && runtime.GOARCH != "mips64le" {
index 04382e6208887e2df1e2cdcf12e3fae0abdb15bd..6e5eb4ba6ade8e9f39bc95032a42f4df8dc9cc91 100644 (file)
@@ -285,7 +285,10 @@ func read(p []byte, int63 func() int64, readVal *int64, readPos *int8) (n int, e
  * Top-level convenience functions
  */
 
-var globalRand = New(&lockedSource{src: NewSource(1).(Source64)})
+var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)})
+
+// Type assert that globalRand's source is a lockedSource whose src is a *rngSource.
+var _ *rngSource = globalRand.src.(*lockedSource).src
 
 // Seed uses the provided seed value to initialize the default Source to a
 // deterministic state. If Seed is not called, the generator behaves as
@@ -373,7 +376,7 @@ func ExpFloat64() float64 { return globalRand.ExpFloat64() }
 
 type lockedSource struct {
        lk  sync.Mutex
-       src Source64
+       src *rngSource
 }
 
 func (r *lockedSource) Int63() (n int64) {
index ee9c8f8e84b33e68961c7b2193fa49da94a8fcd2..e037aaed0ea178402cff2a91312404bbd3b18290 100644 (file)
@@ -565,6 +565,14 @@ func BenchmarkInt63Threadsafe(b *testing.B) {
        }
 }
 
+func BenchmarkInt63ThreadsafeParallel(b *testing.B) {
+       b.RunParallel(func(pb *testing.PB) {
+               for pb.Next() {
+                       Int63()
+               }
+       })
+}
+
 func BenchmarkInt63Unthreadsafe(b *testing.B) {
        r := New(NewSource(1))
        for n := b.N; n > 0; n-- {