Repository navigation
perf: size decoded header maps from recent header blocks - #999
Open
patrick-immometrica wants to merge 1 commit into
Open
patrick-immometrica wants to merge 1 commit into
patrick-immometrica wants to merge 1 commit into
Conversation
Every HEADERS frame was decoded into a fresh HeaderMap::new(), so a typical request of 8-30 fields rehashed the map two or three times while decoding. FrameDecoder now keeps a moving average of the field count of recent blocks and creates the next block's map with that capacity. The first block on a connection is unchanged, and the hint is capped at 64 so a single large block doesn't make later ones over-reserve.
patrick-immometrica
marked this pull request as ready for review
November 5, 2026 17:28
This branch has not been deployed
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.
Follow-up to hyperium/http#886, where the suggestion was to keep a moving average in the parser instead of changing how
HeaderMapgrows.Every HEADERS frame is decoded into a fresh
HeaderMap::new(), so a request with 8-30 fields rehashes the map two or three times while it's being decoded.FrameDecodernow keeps a moving average of the field count of recent header blocks and creates the next block's map with that capacity. The newest block weighs 1/4 and the average rounds up, so a steady count doesn't decay. It's capped at 64 so one huge block doesn't make the following ones over-reserve. The first block on a connection is unchanged since the hint starts at 0.I counted instructions with cachegrind (Linux,
rust:1container): 10k browser-like GET requests encoded with h2's own hpack encoder, so repeated headers hit the dynamic table like on a real connection, decoded throughdecode_frame. Numbers are per header block with the encode side subtracted.Only HEADERS frames feed the average, PUSH_PROMISE just uses it. I added a unit test that checks the map is reserved before any field is decoded into it and that the hint stays at the cap.