Perf: avoid using rand.Rand casting
This commit is contained in:
parent
19fdd70713
commit
4b9164bd75
|
@ -4,8 +4,11 @@ import (
|
|||
crip "crypto/rand"
|
||||
"encoding/binary"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"nullprogram.com/x/rng"
|
||||
|
||||
|
@ -16,11 +19,11 @@ type randPool struct {
|
|||
sync.Pool
|
||||
}
|
||||
|
||||
func (p *randPool) Get() *rand.Rand {
|
||||
return p.Pool.Get().(*rand.Rand)
|
||||
func (p *randPool) Get() *rng.SplitMix64 {
|
||||
return p.Pool.Get().(*rng.SplitMix64)
|
||||
}
|
||||
|
||||
func (p *randPool) Put(r *rand.Rand) {
|
||||
func (p *randPool) Put(r *rng.SplitMix64) {
|
||||
p.Pool.Put(r)
|
||||
}
|
||||
|
||||
|
@ -30,8 +33,7 @@ var (
|
|||
New: func() interface{} {
|
||||
sm64 := new(rng.SplitMix64)
|
||||
sm64.Seed(GetCryptoSeed())
|
||||
prng := rand.New(sm64) //nolint:gosec
|
||||
return prng
|
||||
return sm64
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -42,16 +44,18 @@ var (
|
|||
|
||||
func setSharedRand() {
|
||||
hardLocc.Lock()
|
||||
sharedRand = lolXD.Get()
|
||||
sharedRand = rand.New(lolXD.Get())
|
||||
hardLocc.Unlock()
|
||||
}
|
||||
|
||||
func AcquireRand() *rand.Rand {
|
||||
return lolXD.Get()
|
||||
return rand.New(lolXD.Get())
|
||||
}
|
||||
|
||||
func ReleaseRand(r *rand.Rand) {
|
||||
lolXD.Put(r)
|
||||
srcField := reflect.ValueOf(r).Elem().FieldByName("src")
|
||||
src := reflect.NewAt(srcField.Type(), unsafe.Pointer(srcField.UnsafeAddr())).Elem().Interface().(*rng.SplitMix64)
|
||||
lolXD.Put(src)
|
||||
r = nil
|
||||
}
|
||||
|
||||
|
@ -80,18 +84,17 @@ func GetOptimizedRand() *rand.Rand {
|
|||
}
|
||||
|
||||
// GetSharedRand returns a pointer to our shared optimized rand.Rand which uses crypto/rand to seed a splitmix64 rng.
|
||||
// WARNING - RACY - This is not thread safe, and should only be used in a single-threaded context.
|
||||
func GetSharedRand() *rand.Rand {
|
||||
getSharedRand.Do(func() {
|
||||
setSharedRand()
|
||||
})
|
||||
return sharedRand
|
||||
return rand.New(sharedRand)
|
||||
}
|
||||
|
||||
// RNGUint32 returns a random uint32 using crypto/rand and splitmix64.
|
||||
func RNGUint32() uint32 {
|
||||
r := lolXD.Get()
|
||||
ui := r.Uint32()
|
||||
ui := uint32(r.Int63() >> 31)
|
||||
lolXD.Put(r)
|
||||
return ui
|
||||
}
|
||||
|
@ -106,8 +109,25 @@ RNG returns integer with a maximum amount of 'n' using a global/shared instance
|
|||
*/
|
||||
func RNG(n int) int {
|
||||
r := lolXD.Get()
|
||||
i := r.Intn(n)
|
||||
lolXD.Put(r)
|
||||
defer lolXD.Put(r)
|
||||
i := 0
|
||||
if n <= 0 {
|
||||
// because panic is just rude.
|
||||
_, _ = os.Stderr.WriteString("RNG: n must be greater than 0, returning 0")
|
||||
return i
|
||||
}
|
||||
if n <= 1<<31-1 {
|
||||
n32 := int32(n)
|
||||
if n32&(n32-1) == 0 {
|
||||
i = int(int32(r.Int63()>>32) & (n32 - 1))
|
||||
}
|
||||
maximum := int32((1 << 31) - 1 - (1<<31)%uint32(n32))
|
||||
v := int32(r.Int63() >> 32)
|
||||
for v > maximum {
|
||||
v = int32(r.Int63() >> 32)
|
||||
}
|
||||
i = int(v % n32)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
|
@ -167,7 +187,7 @@ func randStr(upper bool, size int) string {
|
|||
buf := strBufs.Get()
|
||||
r := lolXD.Get()
|
||||
for i := 0; i != size; i++ {
|
||||
ui32 := int(r.Uint32())
|
||||
ui32 := int(r.Int63() >> 31)
|
||||
switch upper {
|
||||
case true:
|
||||
_ = buf.WriteByte(charsetWithUpper[ui32%len(charsetWithUpper)])
|
||||
|
|
|
@ -49,15 +49,15 @@ func Test_RNG(t *testing.T) {
|
|||
t.Errorf("GetSharedRand(55555) returned the same value twice!")
|
||||
}
|
||||
r := AcquireRand()
|
||||
one := r.Intn(55555)
|
||||
two := r.Intn(55555)
|
||||
one := r.Uint64()
|
||||
two := r.Uint64()
|
||||
if one == two {
|
||||
t.Errorf("AcquireRand() returned the same value twice!")
|
||||
}
|
||||
ReleaseRand(r)
|
||||
r = AcquireRand()
|
||||
one1 := r.Intn(55555)
|
||||
two1 := r.Intn(55555)
|
||||
one1 := r.Uint64()
|
||||
two1 := r.Uint64()
|
||||
if one1 == two1 {
|
||||
t.Errorf("AcquireRand() returned the same value twice!")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue