codeberg.org/gruf/go-pools@v1.1.0/pool_test.go (about) 1 package pools_test 2 3 import ( 4 "sync" 5 "sync/atomic" 6 "testing" 7 "time" 8 9 "codeberg.org/gruf/go-pools" 10 ) 11 12 type badPool struct { 13 New func() interface{} 14 Evict func(interface{}) 15 pool []interface{} 16 mu sync.Mutex 17 } 18 19 func (p *badPool) startEvicts() { 20 for { 21 time.Sleep(time.Second) 22 p.mu.Lock() 23 if len(p.pool) > 1 { 24 l := len(p.pool) - 1 25 v := p.pool[l] 26 p.pool = p.pool[:l-1] 27 p.Evict(v) 28 } 29 p.mu.Unlock() 30 } 31 } 32 33 func (p *badPool) Get() interface{} { 34 p.mu.Lock() 35 if len(p.pool) < 1 { 36 p.mu.Unlock() 37 return p.New() 38 } 39 l := len(p.pool) - 1 40 v := p.pool[l] 41 p.pool = p.pool[:l] 42 p.mu.Unlock() 43 return v 44 } 45 46 func (p *badPool) Put(v interface{}) { 47 if v == nil { 48 return 49 } 50 p.mu.Lock() 51 p.pool = append(p.pool, v) 52 p.mu.Unlock() 53 } 54 55 type testItem struct { 56 i int32 57 } 58 59 func (i *testItem) check() bool { 60 defer atomic.StoreInt32(&i.i, 0) 61 return atomic.CompareAndSwapInt32(&i.i, 0, 1) 62 } 63 64 func BenchmarkPool(b *testing.B) { 65 p := &pools.Pool{} 66 67 p.New = func() interface{} { 68 return &testItem{} 69 } 70 71 p.Evict = func(i interface{}) { 72 if !i.(*testItem).check() { 73 panic("in use during eviction") 74 } 75 } 76 77 b.ResetTimer() 78 b.ReportAllocs() 79 b.RunParallel(func(pb *testing.PB) { 80 for pb.Next() { 81 i := p.Get().(*testItem) 82 if !i.check() { 83 panic("in use after get") 84 } 85 p.Put(i) 86 } 87 }) 88 } 89 90 func BenchmarkSyncPool(b *testing.B) { 91 p := sync.Pool{} 92 93 p.New = func() interface{} { 94 return &testItem{} 95 } 96 97 b.ResetTimer() 98 b.ReportAllocs() 99 b.RunParallel(func(pb *testing.PB) { 100 for pb.Next() { 101 i := p.Get().(*testItem) 102 if !i.check() { 103 panic("in use after get") 104 } 105 p.Put(i) 106 } 107 }) 108 } 109 110 func BenchmarkBadPool(b *testing.B) { 111 p := badPool{} 112 go p.startEvicts() 113 114 p.New = func() interface{} { 115 return &testItem{} 116 } 117 118 p.Evict = func(i interface{}) { 119 if !i.(*testItem).check() { 120 panic("in use during eviction") 121 } 122 } 123 124 b.ResetTimer() 125 b.ReportAllocs() 126 b.RunParallel(func(pb *testing.PB) { 127 for pb.Next() { 128 i := p.Get().(*testItem) 129 if !i.check() { 130 panic("in use after get") 131 } 132 p.Put(i) 133 } 134 }) 135 }