aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlo Alberto Ferraris <cafxx@strayorange.com>2019-08-24 08:59:01 +0900
committerEmmanuel Odeke <emm.odeke@gmail.com>2019-09-29 14:27:05 +0000
commit931365763a294950200096d071a35f799ffade2c (patch)
treead6eb4ac98137df44e6a3b0dc74f5c7bcb4f378e /src
parent57662b1575030aa09043cd7a48425abdc6e0e0a3 (diff)
downloadgo-931365763a294950200096d071a35f799ffade2c.tar.xz
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>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/gc/inl_test.go4
-rw-r--r--src/math/rand/rand.go7
-rw-r--r--src/math/rand/rand_test.go8
3 files changed, 17 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/gc/inl_test.go b/src/cmd/compile/internal/gc/inl_test.go
index a0f56e776b..77c398af82 100644
--- a/src/cmd/compile/internal/gc/inl_test.go
+++ b/src/cmd/compile/internal/gc/inl_test.go
@@ -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" {
diff --git a/src/math/rand/rand.go b/src/math/rand/rand.go
index 04382e6208..6e5eb4ba6a 100644
--- a/src/math/rand/rand.go
+++ b/src/math/rand/rand.go
@@ -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) {
diff --git a/src/math/rand/rand_test.go b/src/math/rand/rand_test.go
index ee9c8f8e84..e037aaed0e 100644
--- a/src/math/rand/rand_test.go
+++ b/src/math/rand/rand_test.go
@@ -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-- {