From d2c5fcbdfb533b9053f8930a050f60ade93727db Mon Sep 17 00:00:00 2001 From: Matheus Degiovani Date: Tue, 5 Mar 2024 17:28:32 -0300 Subject: [PATCH] bufferpool: Switch to zeropool This commit switches the bufferpool to use the zeropool implementation for sync pools. The stdlib sync.Pool implementation has an issue where it causes an additional heap allocation per Put() call when used with byte slices. github.com/colega/zeropool package has been specifically designed to work around this issue, which reduces GC pressure and improves performance. This also fixes the bufferpool's pkg benchmark to use a new pool per test, to avoid other tests influencing the behavior of the benchmark and sets it to report the allocations. --- exp/bufferpool/pool.go | 14 ++++++++------ exp/bufferpool/pool_test.go | 13 +++++++++++-- go.mod | 1 + go.sum | 2 ++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/exp/bufferpool/pool.go b/exp/bufferpool/pool.go index 22112687..170917d8 100644 --- a/exp/bufferpool/pool.go +++ b/exp/bufferpool/pool.go @@ -3,6 +3,8 @@ package bufferpool import ( "sync" + + "github.com/colega/zeropool" ) const ( @@ -90,20 +92,20 @@ func (p *Pool) init() { // still maximizing reuse of buffers allocated by Get. // Note that we cannot simply use n.buckets[idx].New, // as this would side-step pooling. - p.buckets[i].New = p.buckets[idx].Get + p.buckets[i] = zeropool.New(p.buckets[idx].Get) } else { - p.buckets[i].New = newAllocFunc(i) + p.buckets[i] = zeropool.New(newAllocFunc(i)) } } }) } -type bucketSlice []sync.Pool +type bucketSlice []zeropool.Pool[[]byte] func (bs bucketSlice) Get(size int) []byte { for i := range bs { if 1<= size { - return bs[i].Get().([]byte) + return bs[i].Get() } } @@ -119,8 +121,8 @@ func (bs bucketSlice) Put(buf []byte) { } } -func newAllocFunc(i int) func() any { - return func() any { +func newAllocFunc(i int) func() []byte { + return func() []byte { return make([]byte, 1<