Skip to content

Bug: Per-message heap allocation in receive hot path #155

Description

@dustinblack

Summary

The receive path allocates a new Vec<u8> on every message across all transports, violating the project's own measurement accuracy guideline in AGENTS.md:

Avoid allocations in send/receive hot loops.

This adds allocator jitter to every measured latency sample. Sporadic allocator overhead (bin traversal, mmap/brk for new pages) inflates tail percentiles with noise from the tool, not from the transport.

Affected Code Paths

TCP/UDS (blocking): bincode::deserialize() constructs a new Message with a new Vec<u8> payload on every receive.

SHM ring buffer (blocking): read_data_blocking() calls Vec::with_capacity(data_len) per message (avoids zero-fill but still allocates).

SHM-direct: receive_blocking() calls Vec::with_capacity(payload_len) per message.

PMQ (blocking): vec![0u8; self.max_msg_size] per receive — allocates AND zero-fills.

Expected Behavior

Pre-allocate the receive buffer once at setup and reuse it across all iterations, similar to what standalone_client.rs already does for the send side ("Create message once, reuse across iterations to avoid per-message heap allocation").

For transports where deserialization produces a new Message struct (bincode), the deserialization target should be a pre-allocated buffer that is overwritten in-place rather than a fresh allocation.

Impact

Estimated overhead per allocation: ~50-200ns on the fast path (glibc ptmalloc2 same-size reuse), with occasional spikes of 1-10µs when the allocator coalesces or calls mmap. On a benchmark measuring 25-100µs RTT, this is 0.2-4% of the signal at median, and a significant contributor to tail noise.

Context

Identified during a comparative evaluation of IPC benchmark approaches. A comparable C++20 benchmark allocates one packet buffer at startup and receives directly into it — zero per-message allocations in the measured path. The difference is visible in tail latency stability.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions