Skip to content

Refund HTTP/2 connection credit for buffered DATA - #1

Open
hiroTamada wants to merge 2 commits into
masterfrom
hypeship/refund-h2-conn-window
Open

Refund HTTP/2 connection credit for buffered DATA#1
hiroTamada wants to merge 2 commits into
masterfrom
hypeship/refund-h2-conn-window

Conversation

@hiroTamada

@hiroTamada hiroTamada commented Aug 29, 2026

Copy link
Copy Markdown

summary

  • return connection-level HTTP/2 flow-control credit after response DATA is buffered
  • keep stream-level credit tied to application body reads
  • avoid duplicate connection credit on response-body close
  • batch connection-level WINDOW_UPDATEs: refunds accumulate in unsentConnRefund and are announced once they reach half the connection window, instead of one frame + flush per DATA frame — avoids hot-path write amplification and a per-frame stream-0 WINDOW_UPDATE cadence that no real browser produces
  • add a regression test for paused response bodies exhausting a connection, plus assert exactly-once refunds (no double credit) in the unused-flow-control test

why this diverges from upstream x/net

upstream returns connection credit on body reads and never hits this starvation because its default connection window is 1 GB against 4 MB stream windows. fhttp advertises browser-realistic windows (ConnectionFlow 15663105 with 6 MB streams for Chrome), so three unread bodies can pin the whole connection window. refunding at buffer time is required here; the batching mirrors the accumulate-and-threshold approach upstream adopted in CL 448155 (inflow).

testing

  • go test -vet=off -run 'TestTransportPausedBodiesDoNotExhaustConnectionWindow' -count=10 ./http2
  • go test -race -vet=off -run 'TestTransportPausedBodiesDoNotExhaustConnectionWindow|TestTransportReturnsUnusedFlowControl|TestTransportReturnsDataPaddingFlowControl' -count=3 ./http2
  • go test -vet=off -run 'TestTransportReturnsUnusedFlowControl|TestTransportReturnsDataPaddingFlowControl|TestTransportAdjustsFlowControl' ./http2
  • full package tests not run as a gate: the repository has pre-existing failures under the current toolchain (including TestTransportFlowControl and a nil-pointer panic in legacy server tests). verified the failure set is byte-identical between this branch and its base.

@hiroTamada
hiroTamada marked this pull request as ready for review August 29, 2026 00:46
@hiroTamada
hiroTamada requested a review from rgarcia August 29, 2026 18:20

@rgarcia rgarcia left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

approving — the fix is right and the mechanism checks out. verified the regression test fails on base without the fix, race detector is clean, and the full-suite failure set is byte-identical to master, so the pre-existing breakage claim holds. batching the stream-0 WINDOW_UPDATEs to a half-window cadence instead of per-frame is the right call for the fingerprint too.

one question before we tag a release and bump consumers: the connection window was incidentally the only cap on unread buffered body data per connection (~15.7MB). after this it's 6MB × concurrent streams — we've observed 100+ open unread bodies on a busy host, so worst case is potentially hundreds of MB per connection with nothing bounding the dataBuffer growth. that's what chrome does too, but chrome has its own memory accounting on top and we don't.

can we either:

  1. size it — what's the p99 concurrent unread bodies per pooled connection under real load? if it's <20 this is a non-issue, or
  2. add telemetry — a gauge for buffered-unread bytes per ClientConn (sum of bufPipe lengths) exposed so callers can export it, and we watch process RSS during rollout

either answers it. (2) is probably worth having regardless since this class of bug was invisible until we added body-level tracking.

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