pool io.Copy buffers in ioCopier to reduce GC pressure#49
Open
Conversation
Replace the cureent io.Copy with the io.CopyBuffer with pooled buffer
There was a problem hiding this comment.
Pull request overview
This PR reduces allocation/GC pressure in high-throughput pipelines by reusing a shared 32KB buffer for ioCopier copy operations, avoiding io.Copy’s per-call buffer allocation in the common pipe FD case.
Changes:
- Introduce a package-level
sync.Poolthat hands out reusable 32KB copy buffers. - Switch
ioCopierfromio.Copytoio.CopyBufferusing the pooled buffer.
Show a summary per file
| File | Description |
|---|---|
pipe/iocopier.go |
Adds a pooled 32KB buffer and uses io.CopyBuffer to reduce allocations during copying. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 1/1 changed files
- Comments generated: 0
carlosmn
approved these changes
Apr 7, 2026
This is surprising. I thought I had checked some time back that you do end up with one of these for file descriptors. Or maybe we erase the type enough that the runtime can't tell. |
znull
approved these changes
Apr 7, 2026
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.
While doing some perfomance analysis in one of our internal services I found that pipelines using the library showed relatively big allocation rates (12.6 MB/s).
io.Copyallocates a fresh 32KB buffer on every call when neither the reader nor writer implements ReadFrom/WriterTo, which is the common case forioCopiersince it typically copies between pipe file descriptors.In high-throughput services this makes
io.copyBufferone of the top allocation sources. A 20-second heap profile showed 255MB allocated from io.copyBuffer, contributing ~12.6 MB/s of allocation pressure and driving GC worker saturation to ~70% of available procs per cycle.The change introduced here adds a
sync.Poolof *[]byte (32KB, matching io.Copy's default) and use io.CopyBuffer with the pooled buffer. The buffer is returned to the pool after each copy completes.This is a safe, drop-in change:
io.CopyBufferhas identical semantics toio.Copywhen a buffer is provided.