Skip to content

pool io.Copy buffers in ioCopier to reduce GC pressure#49

Open
migue wants to merge 1 commit intomainfrom
git-systems/pooled-copies
Open

pool io.Copy buffers in ioCopier to reduce GC pressure#49
migue wants to merge 1 commit intomainfrom
git-systems/pooled-copies

Conversation

@migue
Copy link
Copy Markdown
Collaborator

@migue migue commented Apr 7, 2026

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.Copy allocates a fresh 32KB buffer on every call when neither the reader nor writer implements ReadFrom/WriterTo, which is the common case for ioCopier since it typically copies between pipe file descriptors.

In high-throughput services this makes io.copyBuffer one 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.Pool of *[]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.CopyBuffer has identical semantics to io.Copy when a buffer is provided.

Replace the cureent io.Copy with the io.CopyBuffer with pooled buffer
@migue migue requested a review from a team as a code owner April 7, 2026 13:32
Copilot AI review requested due to automatic review settings April 7, 2026 13:32
@migue migue self-assigned this Apr 7, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.Pool that hands out reusable 32KB copy buffers.
  • Switch ioCopier from io.Copy to io.CopyBuffer using 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
Copy link
Copy Markdown

carlosmn commented Apr 7, 2026

when neither the reader nor writer implements ReadFrom/WriterTo, which is the common case for ioCopier since it typically copies between pipe file descriptors.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants