github.com/zeebo/mon@v0.0.0-20211012163247-13d39bdb54fa/internal/tests/helpers.go (about) 1 package tests 2 3 import ( 4 "fmt" 5 "runtime" 6 "sync" 7 "testing" 8 "unsafe" 9 10 "github.com/zeebo/pcg" 11 ) 12 13 var Value = unsafe.Pointer(new(int)) 14 15 func Empty() unsafe.Pointer { return Value } 16 17 const ( 18 Size = 1 << 14 19 Mask = Size - 1 20 ) 21 22 var ( 23 ptrs = make([]unsafe.Pointer, Size) 24 keys = make([]string, Size) 25 ) 26 27 func init() { 28 for i := range ptrs { 29 ptrs[i&Mask] = unsafe.Pointer(new(int)) 30 keys[i&Mask] = fmt.Sprintf("%064d", i) 31 } 32 } 33 34 func Ptr(i uint32) (p unsafe.Pointer) { return ptrs[i&Mask] } 35 36 func Key(i uint32) (s string) { return keys[i&Mask] } 37 38 type Type interface { 39 Upsert(string, func() unsafe.Pointer) unsafe.Pointer 40 Lookup(string) unsafe.Pointer 41 } 42 43 func RunBenchmarks(b *testing.B, fn func() Type) { 44 rng := pcg.New(0) 45 46 b.Run("UpsertFull", func(b *testing.B) { 47 b.ReportAllocs() 48 49 for i := 0; i < b.N; i++ { 50 t := fn() 51 for i := 0; i < Size; i++ { 52 t.Upsert(Key(rng.Uint32n(Size)), Empty) 53 } 54 } 55 }) 56 57 b.Run("Upsert", func(b *testing.B) { 58 t := fn() 59 b.ReportAllocs() 60 61 for i := 0; i < b.N; i++ { 62 t.Upsert(Key(rng.Uint32n(Size)), Empty) 63 } 64 }) 65 66 b.Run("Lookup", func(b *testing.B) { 67 var sink unsafe.Pointer 68 t := fn() 69 for i := uint32(0); i < Size; i++ { 70 t.Upsert(Key(i), Empty) 71 } 72 b.ReportAllocs() 73 b.ResetTimer() 74 75 for i := 0; i < b.N; i++ { 76 sink = t.Lookup(Key(rng.Uint32n(Size))) 77 } 78 79 runtime.KeepAlive(sink) 80 }) 81 82 b.Run("UpsertParallel", func(b *testing.B) { 83 t := fn() 84 b.ReportAllocs() 85 b.ResetTimer() 86 87 b.RunParallel(func(pb *testing.PB) { 88 rng := pcg.New(pcg.Uint64()) 89 for pb.Next() { 90 t.Upsert(Key(rng.Uint32n(Size)), Empty) 91 } 92 }) 93 }) 94 95 b.Run("UpsertFullParallel", func(b *testing.B) { 96 procs := runtime.GOMAXPROCS(-1) 97 iters := Size / procs 98 b.ReportAllocs() 99 100 for i := 0; i < b.N; i++ { 101 t := fn() 102 var wg sync.WaitGroup 103 104 for i := 0; i < procs; i++ { 105 wg.Add(1) 106 go func() { 107 rng := pcg.New(pcg.Uint64()) 108 for i := 0; i < iters; i++ { 109 t.Upsert(Key(rng.Uint32n(Size)), Empty) 110 } 111 wg.Done() 112 }() 113 } 114 wg.Wait() 115 } 116 }) 117 }