fix: return currentBuffer and prevTail to dstPool in init to stop leak#69
Merged
klauspost merged 2 commits intoApr 22, 2026
Merged
Conversation
Writer.init unconditionally cleared z.currentBuffer and z.prevTail to nil, which on a Reset/Close cycle dropped a fully-allocated buffer and an optional tail buffer on the floor every iteration. Both had just been fetched from z.dstPool on the preceding Close path (compressCurrent at gzip.go:272 / Close calling compressCurrent with flush=true), so the pool never saw them again. Long-running hot loops that reuse a single Writer with Reset(buf); Write; Close; ... grew allocations without bound as the sync.Pool hit-rate collapsed (klauspost#56). Put both buffers back before zeroing them. The existing 'Put in .compressBlock' and 'Put p / Put prevTail' call sites show the pattern already in use for the other Get locations - this change just extends it to the init path so the pool is complete. Behavioural note: init runs only from NewWriter and from Reset (via SetConcurrency). In NewWriter the fields are the zero-value nil, the new guards short-circuit, and nothing changes. Only the Reset path benefits, which is the path that users complained about. Closes klauspost#56 Signed-off-by: SAY-5 <SAY-5@users.noreply.github.com>
klauspost
reviewed
Apr 22, 2026
No need to describe what can easily be seen in code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #56.
Writer.initunconditionally clearedz.currentBufferandz.prevTailtonil. On aReset/Closecycle that dropped a fully-allocated buffer (and an optional tail buffer) on the floor every iteration: both had just been fetched fromz.dstPoolon the precedingClosepath (compressCurrentat gzip.go:272,ClosecallingcompressCurrentwithflush=true), so the pool never saw them again.Long-running hot loops that reuse a single Writer with
Reset(buf); Write; Close; ...grew allocations without bound as the sync.Pool hit-rate collapsed.Fix
Put both buffers back before zeroing them. The existing
// Put in .compressBlockandPut p / Put prevTailcall sites (lines 272, 397, 441, 458) show the pattern already in use for the otherGetlocations - this change just extends it to the init path so the pool is complete.Behaviour
NewWriter→initon a fresh*Writer: both fields are zero-valuenil, the new guards short-circuit, nothing changes.Reset→SetConcurrency→initafter aClose: both fields hold live pool buffers, they are returned, and the pool stays healthy.Verification
Locally on macOS, go 1.26.2:
gofmt -s -l: cleango vet ./...: cleango test -race -count=1 ./...: pass (full suite, ~130s under -race)Closes #56