perf(http2): reserve minimal send capacity when piping request bodies - #4149
Merged
seanmonstar merged 1 commit intoAug 10, 2026
Merged
Conversation
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
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.
[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.