From e3d213c18a9450368293011f6aa31c168903d97d Mon Sep 17 00:00:00 2001 From: Arjan Bal Date: Fri, 24 Oct 2025 01:49:31 +0530 Subject: [PATCH 1/2] avoid necessary clears --- mem/buffer_pool.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/mem/buffer_pool.go b/mem/buffer_pool.go index c37c58c0233e..aab5a50fd615 100644 --- a/mem/buffer_pool.go +++ b/mem/buffer_pool.go @@ -118,7 +118,11 @@ type sizedBufferPool struct { } func (p *sizedBufferPool) Get(size int) *[]byte { - buf := p.pool.Get().(*[]byte) + buf, ok := p.pool.Get().(*[]byte) + if !ok { + buf := make([]byte, size, p.defaultSize) + return &buf + } b := *buf clear(b[:cap(b)]) *buf = b[:size] @@ -137,12 +141,6 @@ func (p *sizedBufferPool) Put(buf *[]byte) { func newSizedBufferPool(size int) *sizedBufferPool { return &sizedBufferPool{ - pool: sync.Pool{ - New: func() any { - buf := make([]byte, size) - return &buf - }, - }, defaultSize: size, } } From c237d601386fd865e0a026eb6f67ae990df45a38 Mon Sep 17 00:00:00 2001 From: Arjan Bal Date: Fri, 24 Oct 2025 01:49:46 +0530 Subject: [PATCH 2/2] clear simple pool buffers --- mem/buffer_pool.go | 1 + mem/buffer_pool_test.go | 52 +++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/mem/buffer_pool.go b/mem/buffer_pool.go index aab5a50fd615..798a0635184e 100644 --- a/mem/buffer_pool.go +++ b/mem/buffer_pool.go @@ -158,6 +158,7 @@ type simpleBufferPool struct { func (p *simpleBufferPool) Get(size int) *[]byte { bs, ok := p.pool.Get().(*[]byte) if ok && cap(*bs) >= size { + clear((*bs)[:cap(*bs)]) *bs = (*bs)[:size] return bs } diff --git a/mem/buffer_pool_test.go b/mem/buffer_pool_test.go index 9a9d850ce369..6086805674ba 100644 --- a/mem/buffer_pool_test.go +++ b/mem/buffer_pool_test.go @@ -49,26 +49,44 @@ func (s) TestBufferPool(t *testing.T) { } func (s) TestBufferPoolClears(t *testing.T) { - pool := mem.NewTieredBufferPool(4) + const poolSize = 4 + pool := mem.NewTieredBufferPool(poolSize) + tests := []struct { + name string + bufferSize int + }{ + { + name: "sized_buffer_pool", + bufferSize: poolSize, + }, + { + name: "simple_buffer_pool", + bufferSize: poolSize + 1, + }, + } - for { - buf1 := pool.Get(4) - copy(*buf1, "1234") - pool.Put(buf1) + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + for { + buf1 := pool.Get(tc.bufferSize) + copy(*buf1, "1234") + pool.Put(buf1) - buf2 := pool.Get(4) - if unsafe.SliceData(*buf1) != unsafe.SliceData(*buf2) { - pool.Put(buf2) - // This test is only relevant if a buffer is reused, otherwise try again. This - // can happen if a GC pause happens between putting the buffer back in the pool - // and getting a new one. - continue - } + buf2 := pool.Get(tc.bufferSize) + if unsafe.SliceData(*buf1) != unsafe.SliceData(*buf2) { + pool.Put(buf2) + // This test is only relevant if a buffer is reused, otherwise try again. This + // can happen if a GC pause happens between putting the buffer back in the pool + // and getting a new one. + continue + } - if !bytes.Equal(*buf1, make([]byte, 4)) { - t.Fatalf("buffer not cleared") - } - break + if !bytes.Equal(*buf1, make([]byte, tc.bufferSize)) { + t.Fatalf("buffer not cleared") + } + break + } + }) } }