aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhangyunhao <zhangyunhao@bytedance.com>2022-04-18 15:23:20 +0800
committerGopher Robot <gobot@golang.org>2022-04-20 22:50:33 +0000
commitebe1435fbb50bb82bfca53063e8daba4f870ec8d (patch)
treed14d2583cbcdcd519ce32def65497fe2dce30f43
parent6de00888e4720b7fa23ef2ce294bc3e81b866b0f (diff)
downloadgo-ebe1435fbb50bb82bfca53063e8daba4f870ec8d.tar.gz
go-ebe1435fbb50bb82bfca53063e8daba4f870ec8d.zip
runtime: add fastrand64
Support fastrand64 in the runtime, although fastrand uses wyrand to generate 64-bit random number, it still returns uint32. In some cases, we need to generate a 64-bit random number, the new API would be faster and easier to use, and at least we can use the new function in these places: src/net/dnsclient.go:randInt() src/hash/maphash/maphash.go:MakeSeed() src/runtime/map.go:mapiterinit() name time/op Fastrand-16 0.09ns ± 5% Fastrand64-16 0.09ns ± 6% Change-Id: Ibb97378c7ca59bc7dc15535d4872fa58ea112e6a Reviewed-on: https://go-review.googlesource.com/c/go/+/400734 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com>
-rw-r--r--src/runtime/export_test.go1
-rw-r--r--src/runtime/rand_test.go8
-rw-r--r--src/runtime/stubs.go39
3 files changed, 48 insertions, 0 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index af27050bfd..8a81f42ca0 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -277,6 +277,7 @@ func CountPagesInUse() (pagesInUse, counted uintptr) {
}
func Fastrand() uint32 { return fastrand() }
+func Fastrand64() uint64 { return fastrand64() }
func Fastrandn(n uint32) uint32 { return fastrandn(n) }
type ProfBuf profBuf
diff --git a/src/runtime/rand_test.go b/src/runtime/rand_test.go
index 1b84c79d24..92d07ebada 100644
--- a/src/runtime/rand_test.go
+++ b/src/runtime/rand_test.go
@@ -18,6 +18,14 @@ func BenchmarkFastrand(b *testing.B) {
})
}
+func BenchmarkFastrand64(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ Fastrand64()
+ }
+ })
+}
+
func BenchmarkFastrandHashiter(b *testing.B) {
var m = make(map[int]int, 10)
for i := 0; i < 10; i++ {
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index 8c4ab3ed4e..ca0cd1ba25 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -157,6 +157,45 @@ func fastrandn(n uint32) uint32 {
return uint32(uint64(fastrand()) * uint64(n) >> 32)
}
+func fastrand64() uint64 {
+ mp := getg().m
+ // Implement wyrand: https://github.com/wangyi-fudan/wyhash
+ // Only the platform that math.Mul64 can be lowered
+ // by the compiler should be in this list.
+ if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|
+ goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|
+ goarch.IsS390x|goarch.IsRiscv64 == 1 {
+ mp.fastrand += 0xa0761d6478bd642f
+ hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db)
+ return hi ^ lo
+ }
+
+ // Implement xorshift64+: 2 32-bit xorshift sequences added together.
+ // Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
+ // This generator passes the SmallCrush suite, part of TestU01 framework:
+ // http://simul.iro.umontreal.ca/testu01/tu01.html
+ t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand))
+ s1, s0 := t[0], t[1]
+ s1 ^= s1 << 17
+ s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
+ r := uint64(s0 + s1)
+
+ s0, s1 = s1, s0
+ s1 ^= s1 << 17
+ s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
+ r += uint64(s0+s1) << 32
+
+ t[0], t[1] = s0, s1
+ return r
+}
+
+func fastrandu() uint {
+ if goarch.PtrSize == 4 {
+ return uint(fastrand())
+ }
+ return uint(fastrand64())
+}
+
//go:linkname sync_fastrandn sync.fastrandn
func sync_fastrandn(n uint32) uint32 { return fastrandn(n) }