diff options
| author | 2026-03-04 08:26:56 +0800 | |
|---|---|---|
| committer | 2026-03-04 08:59:53 +0800 | |
| commit | ab7501be34032fb9e5c48726a68ae90a917af9eb (patch) | |
| tree | 20d005647569befea8133e953c3270e8fd2a2a5b /internal/bufpool | |
| parent | *: gofumpt (diff) | |
| signature | No signature | |
*: Lint
Diffstat (limited to 'internal/bufpool')
| -rw-r--r-- | internal/bufpool/buffers.go | 17 | ||||
| -rw-r--r-- | internal/bufpool/buffers_test.go | 9 |
2 files changed, 26 insertions, 0 deletions
diff --git a/internal/bufpool/buffers.go b/internal/bufpool/buffers.go index a5c27b67..91e30a31 100644 --- a/internal/bufpool/buffers.go +++ b/internal/bufpool/buffers.go @@ -62,9 +62,11 @@ var bufferPools = func() []sync.Pool { capCopy := classCap pools[i].New = func() any { buf := make([]byte, 0, capCopy) + return &buf } } + return pools }() @@ -80,9 +82,11 @@ func Borrow(capHint int) Buffer { if capHint < DefaultBufferCap { capHint = DefaultBufferCap } + classIdx, classCap, pooled := classFor(capHint) if !pooled { newBuf := make([]byte, 0, capHint) + return Buffer{buf: newBuf, pool: unpooled} } //nolint:forcetypeassert @@ -90,7 +94,9 @@ func Borrow(capHint int) Buffer { if cap(*buf) < classCap { *buf = make([]byte, 0, classCap) } + slice := (*buf)[:0] + return Buffer{buf: slice, pool: poolIndex(classIdx)} //#nosec G115 } @@ -110,6 +116,7 @@ func (buf *Buffer) Resize(n int) { if n < 0 { n = 0 } + buf.ensureCapacity(n) buf.buf = buf.buf[:n] } @@ -122,6 +129,7 @@ func (buf *Buffer) Append(src []byte) { if len(src) == 0 { return } + start := len(buf.buf) buf.ensureCapacity(start + len(src)) buf.buf = buf.buf[:start+len(src)] @@ -144,6 +152,7 @@ func (buf *Buffer) Release() { if buf.buf == nil { return } + buf.returnToPool() buf.buf = nil buf.pool = unpooled @@ -157,20 +166,26 @@ func (buf *Buffer) ensureCapacity(needed int) { if cap(buf.buf) >= needed { return } + classIdx, classCap, pooled := classFor(needed) + var newBuf []byte + if pooled { //nolint:forcetypeassert raw := bufferPools[classIdx].Get().(*[]byte) if cap(*raw) < classCap { *raw = make([]byte, 0, classCap) } + newBuf = (*raw)[:len(buf.buf)] } else { newBuf = make([]byte, len(buf.buf), classCap) } + copy(newBuf, buf.buf) buf.returnToPool() + buf.buf = newBuf if pooled { buf.pool = poolIndex(classIdx) //#nosec G115 @@ -185,6 +200,7 @@ func classFor(size int) (idx, classCap int, ok bool) { return i, class, true } } + return -1, size, false } @@ -192,6 +208,7 @@ func (buf *Buffer) returnToPool() { if buf.pool == unpooled { return } + tmp := buf.buf[:0] bufferPools[int(buf.pool)].Put(&tmp) } diff --git a/internal/bufpool/buffers_test.go b/internal/bufpool/buffers_test.go index 70861d33..224fa98c 100644 --- a/internal/bufpool/buffers_test.go +++ b/internal/bufpool/buffers_test.go @@ -15,19 +15,23 @@ func TestBorrowBufferResizeAndAppend(t *testing.T) { b.Append([]byte("alpha")) b.Append([]byte("beta")) + if got := string(b.Bytes()); got != "alphabeta" { t.Fatalf("unexpected contents: %q", got) } b.Resize(3) + if got := string(b.Bytes()); got != "alp" { t.Fatalf("resize shrink mismatch: %q", got) } b.Resize(8) + if len(b.Bytes()) != 8 { t.Fatalf("expected len 8 after grow, got %d", len(b.Bytes())) } + if prefix := string(b.Bytes()[:3]); prefix != "alp" { t.Fatalf("prefix lost after grow: %q", prefix) } @@ -39,6 +43,7 @@ func TestBorrowBufferRelease(t *testing.T) { b := Borrow(DefaultBufferCap / 2) b.Append([]byte("data")) b.Release() + if b.buf != nil { t.Fatal("expected buffer cleared after release") } @@ -59,9 +64,11 @@ func TestBorrowUsesLargerPools(t *testing.T) { if b.pool != poolIndex(classIdx) { t.Fatalf("expected pooled buffer in class %d, got %d", classIdx, b.pool) } + if cap(b.buf) != classCap { t.Fatalf("expected capacity %d, got %d", classCap, cap(b.buf)) } + b.Release() b2 := Borrow(request) @@ -70,6 +77,7 @@ func TestBorrowUsesLargerPools(t *testing.T) { if b2.pool != poolIndex(classIdx) { t.Fatalf("expected pooled buffer in class %d on reuse, got %d", classIdx, b2.pool) } + if cap(b2.buf) != classCap { t.Fatalf("expected capacity %d on reuse, got %d", classCap, cap(b2.buf)) } @@ -82,6 +90,7 @@ func TestGrowingBufferStaysPooled(t *testing.T) { defer b.Release() b.Append(make([]byte, DefaultBufferCap*3)) + if b.pool == unpooled { t.Fatal("buffer should stay pooled after growth within limit") } |
