http2: decode HPACK Huffman strings without repeated slicing - #5102
Conversation
HPACK Huffman decoding rebuilt the remaining bit string on each symbol, making a valid Huffman-coded value cost time quadratic in its length. Decode over the input bytes instead. Full-EOS rejection and the RFC 7541 padding checks are unchanged; integer callers convert to bytes once. Valid short Huffman parses took 50,945.5 ns unmodified and 42,879.6 ns with this change. AI-Assisted: yes (GPT-5.6-Cyber)
|
Adding the numbers I should have put in the description. The two in there (50,945.5 ns → 42,879.6 ns) are only a check that this doesn't slow the normal path — they aren't the benefit. The problem is how the cost grows. The decoder rebuilds the remaining bit string for every symbol, so parsing one valid HEADERS frame costs time proportional to the square of its length:
Eight times the size, roughly forty-four times the work. The same bytes with the Huffman flag cleared parse in under a millisecond, so the cost is entirely in the decoder and not in the surrounding frame handling. Nothing is malformed, and at 16,013 bytes the frame is under the default 16,384-byte maximum — this is something an ordinary client can send. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #5102 +/- ##
==========================================
+ Coverage 79.42% 80.59% +1.16%
==========================================
Files 372 390 +18
Lines 96507 96876 +369
==========================================
+ Hits 76652 78075 +1423
+ Misses 19855 18801 -1054
🚀 New features to boost your workflow:
|
HPACK Huffman decoding rebuilt the remaining bit string on each symbol, so a valid Huffman-coded
value cost time quadratic in its length.
This decodes over the input bytes instead. Full-EOS rejection and the RFC 7541 padding checks are
unchanged; integer callers convert their input to bytes once.
Valid short Huffman parses took 50,945.5 ns unmodified and 42,879.6 ns with the change.
The HTTP/2 tests pass 106 of 106. Two byte-decoding checks were added and fail without the change.