Skip to content

perf(http2): reserve minimal send capacity when piping request bodies - #4149

Merged
seanmonstar merged 1 commit into
hyperium:masterfrom
sandersaares:min-send-capacity-reservation
Aug 10, 2026
Merged

perf(http2): reserve minimal send capacity when piping request bodies#4149
seanmonstar merged 1 commit into
hyperium:masterfrom
sandersaares:min-send-capacity-reservation

Conversation

@sandersaares

Copy link
Copy Markdown
Contributor

[Copilot speaking]

Motivation

#4061 fixed the #4003 deadlock by polling the request body before reserving send capacity, so that a stream can no longer pin connection-level flow-control window against a body that may never produce data. As part of that change, the reservation also grew from a single byte to the full length of the chunk about to be sent.

We associate that second part with a ~10% increase in CPU time per request and a ~12% drop in throughput in a custom load-test environment. The effect only appears under high connection contention — when the streams sharing a connection collectively demand more send capacity than the peer's advertised connection window, so every request has to queue for capacity. Below that threshold it is not measurable.

Claiming the full chunk length makes every in-flight stream a heavyweight claimant in the connection-window distribution for as long as it waits, rather than a stream that is satisfied by its first byte and moves on.

Change

The body pipe now reserves a single byte of send capacity instead of the full chunk length.

The deadlock fix is unaffected. The reservation is still made only once the chunk is in hand, so it can never be pinned by a body that produces nothing. h2 raises the requested send capacity to the buffered length inside send_data, so the demand eventually signalled to the peer is unchanged — only the transient claim held while the stream waits for its first byte of capacity differs.

The reservation size is not observable on the wire, so there is nothing a new test could assert about it; the existing #4003 regression coverage continues to pass.

Reserving the full chunk length makes every in-flight stream a heavyweight
claimant in the connection-window distribution for as long as it waits for
capacity, which is costly once the streams sharing a connection collectively
demand more than the window the peer advertises.

The chunk is still only reserved against once it is in hand, so capacity can
never be pinned by a body that produces nothing (hyperium#4003). h2 raises the
requested send capacity to the buffered length inside `send_data`, so the
demand eventually signalled to the peer is unchanged; only the transient claim
held while the stream waits for its first byte of capacity differs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3296b0a4-b7ac-46e2-8798-c9773b24249d

@seanmonstar seanmonstar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@seanmonstar
seanmonstar merged commit 4cbb929 into hyperium:master Aug 10, 2026
23 checks passed
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.

2 participants