1
0
mirror of https://github.com/golang/go synced 2024-11-18 19:04:40 -07:00

math/rand: devirtualize interface in lockedSource

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>
This commit is contained in:
Carlo Alberto Ferraris 2019-08-24 08:59:01 +09:00 committed by Emmanuel Odeke
parent 57662b1575
commit 931365763a
3 changed files with 17 additions and 2 deletions

View 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" {

View 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) {

View 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-- {