1
0
mirror of https://github.com/golang/go synced 2024-11-16 20:34:51 -07:00

runtime,sync: using fastrandn instead of modulo reduction

fastrandn is ~50% faster than fastrand() % n.
`ack -v 'fastrand\(\)\s?\%'` finds all modulo on fastrand()

name              old time/op  new time/op  delta
Fastrandn/2       2.86ns ± 0%  1.59ns ± 0%  -44.35%  (p=0.000 n=9+10)
Fastrandn/3       2.87ns ± 1%  1.59ns ± 0%  -44.41%  (p=0.000 n=10+9)
Fastrandn/4       2.87ns ± 1%  1.58ns ± 1%  -45.10%  (p=0.000 n=10+10)
Fastrandn/5       2.86ns ± 1%  1.58ns ± 1%  -44.84%  (p=0.000 n=10+10)

Change-Id: Ic91f5ca9b9e3b65127bc34792b62fd64fbd13b5c
Reviewed-on: https://go-review.googlesource.com/c/go/+/353269
Trust: Meng Zhuo <mzh@golangcn.org>
Run-TryBot: Meng Zhuo <mzh@golangcn.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Meng Zhuo 2021-09-30 22:46:09 +08:00
parent 6f74ed06c5
commit ecb2f231fa
6 changed files with 9 additions and 9 deletions

View File

@ -1301,7 +1301,7 @@ func fastexprand(mean int) int32 {
// x = -log_e(q) * mean // x = -log_e(q) * mean
// x = log_2(q) * (-log_e(2)) * mean ; Using log_2 for efficiency // x = log_2(q) * (-log_e(2)) * mean ; Using log_2 for efficiency
const randomBitCount = 26 const randomBitCount = 26
q := fastrand()%(1<<randomBitCount) + 1 q := fastrandn(1<<randomBitCount) + 1
qlog := fastlog2(float64(q)) - randomBitCount qlog := fastlog2(float64(q)) - randomBitCount
if qlog > 0 { if qlog > 0 {
qlog = 0 qlog = 0
@ -1319,7 +1319,7 @@ func nextSampleNoFP() uintptr {
rate = 0x3fffffff rate = 0x3fffffff
} }
if rate != 0 { if rate != 0 {
return uintptr(fastrand() % uint32(2*rate)) return uintptr(fastrandn(uint32(2 * rate)))
} }
return 0 return 0
} }

View File

@ -974,7 +974,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
// machine instructions. // machine instructions.
outOfPlace := false outOfPlace := false
if arenaIndex(x+size-1) != arenaIdx(h.arena) || (doubleCheck && fastrand()%2 == 0) { if arenaIndex(x+size-1) != arenaIdx(h.arena) || (doubleCheck && fastrandn(2) == 0) {
// This object spans heap arenas, so the bitmap may be // This object spans heap arenas, so the bitmap may be
// discontiguous. Unroll it into the object instead // discontiguous. Unroll it into the object instead
// and then copy it out. // and then copy it out.

View File

@ -5840,7 +5840,7 @@ const randomizeScheduler = raceenabled
// If the run queue is full, runnext puts g on the global queue. // If the run queue is full, runnext puts g on the global queue.
// Executed only by the owner P. // Executed only by the owner P.
func runqput(_p_ *p, gp *g, next bool) { func runqput(_p_ *p, gp *g, next bool) {
if randomizeScheduler && next && fastrand()%2 == 0 { if randomizeScheduler && next && fastrandn(2) == 0 {
next = false next = false
} }

View File

@ -156,8 +156,8 @@ func fastrandn(n uint32) uint32 {
return uint32(uint64(fastrand()) * uint64(n) >> 32) return uint32(uint64(fastrand()) * uint64(n) >> 32)
} }
//go:linkname sync_fastrand sync.fastrand //go:linkname sync_fastrandn sync.fastrandn
func sync_fastrand() uint32 { return fastrand() } func sync_fastrandn(n uint32) uint32 { return fastrandn(n) }
//go:linkname net_fastrand net.fastrand //go:linkname net_fastrand net.fastrand
func net_fastrand() uint32 { return fastrand() } func net_fastrand() uint32 { return fastrand() }

View File

@ -921,7 +921,7 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri
if cache != nil { if cache != nil {
x := pcvalueCacheKey(targetpc) x := pcvalueCacheKey(targetpc)
e := &cache.entries[x] e := &cache.entries[x]
ci := fastrand() % uint32(len(cache.entries[x])) ci := fastrandn(uint32(len(cache.entries[x])))
e[ci] = e[0] e[ci] = e[0]
e[0] = pcvalueCacheEnt{ e[0] = pcvalueCacheEnt{
targetpc: targetpc, targetpc: targetpc,

View File

@ -71,7 +71,7 @@ type poolLocal struct {
} }
// from runtime // from runtime
func fastrand() uint32 func fastrandn(n uint32) uint32
var poolRaceHash [128]uint64 var poolRaceHash [128]uint64
@ -92,7 +92,7 @@ func (p *Pool) Put(x interface{}) {
return return
} }
if race.Enabled { if race.Enabled {
if fastrand()%4 == 0 { if fastrandn(4) == 0 {
// Randomly drop x on floor. // Randomly drop x on floor.
return return
} }