Skip to content

Instantly share code, notes, and snippets.

@funny-falcon
Last active January 10, 2017 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save funny-falcon/d8adc39e777b79e56274a65abca29e78 to your computer and use it in GitHub Desktop.
Save funny-falcon/d8adc39e777b79e56274a65abca29e78 to your computer and use it in GitHub Desktop.
Use of runtime.Mid and runtime.Fastrand
package benchmarks
/*
BenchmarkRandInt63_Global-4 10000000 154 ns/op
BenchmarkRandInt63_Channel-4 10000000 220 ns/op
BenchmarkRandInt63_Pool-4 50000000 28.8 ns/op
BenchmarkSourceInt63_Pool-4 50000000 34.9 ns/op
BenchmarkRandInt63_Source-4 300000000 5.71 ns/op
BenchmarkRandInt63_ShardsGettid-4 50000000 29.2 ns/op
BenchmarkRandInt63_ShardsMid-4 100000000 14.2 ns/op
BenchmarkRandInt63_ShardsFastrand-4 30000000 49.0 ns/op
BenchmarkRandInt63_ShardsMidFastrand-4 100000000 17.1 ns/op
*/
import (
"math/rand"
"runtime"
"sync"
"syscall"
"testing"
)
// START_GLOBAL OMIT
func BenchmarkRandInt63_Global(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
rand.Int63() // HL
}
})
}
// END_GLOBAL OMIT
// START_CHANNEL OMIT
func BenchmarkRandInt63_Channel(b *testing.B) {
ch := make(chan int64, 1000) // HL
go func() {
r := rand.New(rand.NewSource(rand.Int63())) // HL
for {
ch <- r.Int63() // HL
}
}()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = <-ch // HL
}
})
}
// END_CHANNEL OMIT
// START_POOL OMIT
func BenchmarkRandInt63_Pool(b *testing.B) {
var pool = sync.Pool{ // HL
New: func() interface{} { // HL
return rand.New(rand.NewSource(rand.Int63())) // HL
}, // HL
} // HL
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
r := pool.Get().(*rand.Rand) // HL
r.Int63()
pool.Put(r) // HL
}
})
}
func BenchmarkSourceInt63_Pool(b *testing.B) {
var pool = sync.Pool{ // HL
New: func() interface{} { // HL
return rand.NewSource(rand.Int63()) // HL
}, // HL
} // HL
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
r := pool.Get().(rand.Source) // HL
r.Int63()
pool.Put(r) // HL
}
})
}
// END_POOL OMIT
// START_SOURCE OMIT
func BenchmarkRandInt63_Source(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
r := rand.New(rand.NewSource(rand.Int63())) // HL
for pb.Next() {
r.Int63()
}
})
}
// END_SOURCE OMIT
func BenchmarkRandInt63_ShardsGettid(b *testing.B) {
rands := make([]*rand.Rand, 32)
for i := range rands {
rands[i] = rand.New(rand.NewSource(rand.Int63()))
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
rands[syscall.Gettid()&31].Int63()
}
})
}
type shard struct {
r *rand.Rand
m sync.Mutex
}
func (sh *shard) Int63() (f int64) {
sh.m.Lock()
f = sh.r.Int63()
sh.m.Unlock()
return
}
const ShardsPerMid = 8
func newShards() (shards []shard) {
shards = make([]shard, runtime.GOMAXPROCS(-1)*ShardsPerMid)
for i := range shards {
shards[i].r = rand.New(rand.NewSource(rand.Int63()))
}
return
}
func BenchmarkRandInt63_ShardsMid(b *testing.B) {
shards := newShards()
l := uint32(len(shards) - 1)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
shards[(runtime.Mid()*ShardsPerMid)&l].Int63()
}
})
}
func BenchmarkRandInt63_ShardsFastrand(b *testing.B) {
shards := newShards()
l := uint32(len(shards) - 1)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
shards[runtime.Fastrand()&l].Int63()
}
})
}
func BenchmarkRandInt63_ShardsMidFastrand(b *testing.B) {
shards := newShards()
l := uint32(len(shards) - 1)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
shards[(runtime.Mid()*ShardsPerMid+runtime.Fastrand()&(ShardsPerMid-1))&l].Int63()
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment