Skip to content

Commit ebe1435

Browse files
zhangyunhao116gopherbot
authored andcommitted
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 <[email protected]> Run-TryBot: Keith Randall <[email protected]> Auto-Submit: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 6de0088 commit ebe1435

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

src/runtime/export_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ func CountPagesInUse() (pagesInUse, counted uintptr) {
277277
}
278278

279279
func Fastrand() uint32 { return fastrand() }
280+
func Fastrand64() uint64 { return fastrand64() }
280281
func Fastrandn(n uint32) uint32 { return fastrandn(n) }
281282

282283
type ProfBuf profBuf

src/runtime/rand_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ func BenchmarkFastrand(b *testing.B) {
1818
})
1919
}
2020

21+
func BenchmarkFastrand64(b *testing.B) {
22+
b.RunParallel(func(pb *testing.PB) {
23+
for pb.Next() {
24+
Fastrand64()
25+
}
26+
})
27+
}
28+
2129
func BenchmarkFastrandHashiter(b *testing.B) {
2230
var m = make(map[int]int, 10)
2331
for i := 0; i < 10; i++ {

src/runtime/stubs.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,45 @@ func fastrandn(n uint32) uint32 {
157157
return uint32(uint64(fastrand()) * uint64(n) >> 32)
158158
}
159159

160+
func fastrand64() uint64 {
161+
mp := getg().m
162+
// Implement wyrand: https://github.com/wangyi-fudan/wyhash
163+
// Only the platform that math.Mul64 can be lowered
164+
// by the compiler should be in this list.
165+
if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|
166+
goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|
167+
goarch.IsS390x|goarch.IsRiscv64 == 1 {
168+
mp.fastrand += 0xa0761d6478bd642f
169+
hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db)
170+
return hi ^ lo
171+
}
172+
173+
// Implement xorshift64+: 2 32-bit xorshift sequences added together.
174+
// Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
175+
// This generator passes the SmallCrush suite, part of TestU01 framework:
176+
// http://simul.iro.umontreal.ca/testu01/tu01.html
177+
t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand))
178+
s1, s0 := t[0], t[1]
179+
s1 ^= s1 << 17
180+
s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
181+
r := uint64(s0 + s1)
182+
183+
s0, s1 = s1, s0
184+
s1 ^= s1 << 17
185+
s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
186+
r += uint64(s0+s1) << 32
187+
188+
t[0], t[1] = s0, s1
189+
return r
190+
}
191+
192+
func fastrandu() uint {
193+
if goarch.PtrSize == 4 {
194+
return uint(fastrand())
195+
}
196+
return uint(fastrand64())
197+
}
198+
160199
//go:linkname sync_fastrandn sync.fastrandn
161200
func sync_fastrandn(n uint32) uint32 { return fastrandn(n) }
162201

0 commit comments

Comments
 (0)