mirror of
https://github.com/golang/go
synced 2024-11-17 03:54:48 -07:00
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>
This commit is contained in:
parent
6de00888e4
commit
ebe1435fbb
@ -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
|
||||
|
@ -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++ {
|
||||
|
@ -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) }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user