]> Cypherpunks.ru repositories - gostls13.git/commitdiff
runtime,sync: using fastrandn instead of modulo reduction
authorMeng Zhuo <mzh@golangcn.org>
Thu, 30 Sep 2021 14:46:09 +0000 (22:46 +0800)
committerMeng Zhuo <mzh@golangcn.org>
Thu, 7 Oct 2021 14:01:52 +0000 (14:01 +0000)
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>
src/runtime/malloc.go
src/runtime/mbitmap.go
src/runtime/proc.go
src/runtime/stubs.go
src/runtime/symtab.go
src/sync/pool.go

index 7affe244a25442dd307c3672bb6116da60d746b3..c389cb1e45c6cad27734c66f12257773734898e9 100644 (file)
@@ -1301,7 +1301,7 @@ func fastexprand(mean int) int32 {
        // x = -log_e(q) * mean
        // x = log_2(q) * (-log_e(2)) * mean    ; Using log_2 for efficiency
        const randomBitCount = 26
-       q := fastrand()%(1<<randomBitCount) + 1
+       q := fastrandn(1<<randomBitCount) + 1
        qlog := fastlog2(float64(q)) - randomBitCount
        if qlog > 0 {
                qlog = 0
@@ -1319,7 +1319,7 @@ func nextSampleNoFP() uintptr {
                rate = 0x3fffffff
        }
        if rate != 0 {
-               return uintptr(fastrand() % uint32(2*rate))
+               return uintptr(fastrandn(uint32(2 * rate)))
        }
        return 0
 }
index 9363409e361c11dfce0b03061fc4f11bcd5de8c3..daf1fcfbc09668994b2295501f747ea5f07383d7 100644 (file)
@@ -974,7 +974,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
        // machine instructions.
 
        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
                // discontiguous. Unroll it into the object instead
                // and then copy it out.
index aa2ba96c8f78d8a56e9ea926afdf7f76dcc2e2fe..c14a1f143c7a8290143f96c518db1e6f4b503c5a 100644 (file)
@@ -5840,7 +5840,7 @@ const randomizeScheduler = raceenabled
 // If the run queue is full, runnext puts g on the global queue.
 // Executed only by the owner P.
 func runqput(_p_ *p, gp *g, next bool) {
-       if randomizeScheduler && next && fastrand()%2 == 0 {
+       if randomizeScheduler && next && fastrandn(2) == 0 {
                next = false
        }
 
index 91380a0d51373fba8129ed846e71b9441d3ab527..ad78363bb67b1184a51eb75be1efff5f489c979a 100644 (file)
@@ -156,8 +156,8 @@ func fastrandn(n uint32) uint32 {
        return uint32(uint64(fastrand()) * uint64(n) >> 32)
 }
 
-//go:linkname sync_fastrand sync.fastrand
-func sync_fastrand() uint32 { return fastrand() }
+//go:linkname sync_fastrandn sync.fastrandn
+func sync_fastrandn(n uint32) uint32 { return fastrandn(n) }
 
 //go:linkname net_fastrand net.fastrand
 func net_fastrand() uint32 { return fastrand() }
index 7641c491f10eb00ae1fffc25078ba6f0ebb3cf83..2de518d2e6a4001837fd5aa11c40f0fc11d03755 100644 (file)
@@ -921,7 +921,7 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri
                        if cache != nil {
                                x := pcvalueCacheKey(targetpc)
                                e := &cache.entries[x]
-                               ci := fastrand() % uint32(len(cache.entries[x]))
+                               ci := fastrandn(uint32(len(cache.entries[x])))
                                e[ci] = e[0]
                                e[0] = pcvalueCacheEnt{
                                        targetpc: targetpc,
index 1ae70127ac24ec137906c7c87dfc28e6ab02d413..9802f29d6f6d5ecb36d9b69b6230d220bad2d51c 100644 (file)
@@ -71,7 +71,7 @@ type poolLocal struct {
 }
 
 // from runtime
-func fastrand() uint32
+func fastrandn(n uint32) uint32
 
 var poolRaceHash [128]uint64
 
@@ -92,7 +92,7 @@ func (p *Pool) Put(x interface{}) {
                return
        }
        if race.Enabled {
-               if fastrand()%4 == 0 {
+               if fastrandn(4) == 0 {
                        // Randomly drop x on floor.
                        return
                }