Skip to content

Shrink compression codec buffers to prevent memory bloat#184

Open
enomado wants to merge 2 commits into
blackbeam:masterfrom
enomado:shrink-compression-buffers
Open

Shrink compression codec buffers to prevent memory bloat#184
enomado wants to merge 2 commits into
blackbeam:masterfrom
enomado:shrink-compression-buffers

Conversation

@enomado
Copy link
Copy Markdown

@enomado enomado commented Apr 6, 2026

Problem

CompPacketCodec's in_buf and out_buf (BytesMut) grow to accommodate large compressed/decompressed packets but never shrink back. Over time every compressed connection accumulates megabytes of idle capacity in these buffers. With 20+ compressed connections this easily wastes 200–500 MB of RSS.

Relates to blackbeam/mysql_async#349.

Fix

After each decode/encode cycle, if a buffer is fully drained (is_empty()) and its allocated capacity exceeds a 4 MiB threshold, replace it with a fresh BytesMut::new().

This is:

  • Zero-cost for normal traffic — the check only fires when buffers are already empty
  • Conservative — 4 MiB threshold avoids churn for reasonably-sized buffers
  • Minimal — 19 lines added, no API changes, no new dependencies

Production status

We've been running an equivalent patch (with a 1 MiB threshold) in production for several months against MySQL 5.1.53 with compression enabled, ~20 concurrent connections. Memory usage dropped from ~400 MB to ~40 MB with no issues.

Open to feedback

If you'd prefer this threshold to be configurable (e.g. via a field on CompPacketCodec or a connection option), happy to rework. The hardcoded constant felt like the least invasive starting point.

enomado and others added 2 commits April 6, 2026 12:08
CompPacketCodec's in_buf and out_buf grow to accommodate large packets
but never shrink, effectively leaking memory for the connection lifetime.
With 20+ compressed connections this wastes 200-500 MB of RSS.

After each decode/encode cycle, if a buffer is fully drained and its
capacity exceeds 4 MiB, replace it with a fresh BytesMut::new().
This is zero-cost for normal-sized packets and only triggers for
genuinely bloated buffers.

Relates to blackbeam/mysql_async#349
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant