Skip to content

transport: skip HPACK indexing for per-RPC-unique request headers - #9377

Open
doroshenkosa wants to merge 1 commit into
grpc:masterfrom
doroshenkosa:transport-hpack-never-index-unique-headers
Open

transport: skip HPACK indexing for per-RPC-unique request headers#9377
doroshenkosa wants to merge 1 commit into
grpc:masterfrom
doroshenkosa:transport-hpack-never-index-unique-headers

Conversation

@doroshenkosa

@doroshenkosa doroshenkosa commented Aug 25, 2026

Copy link
Copy Markdown

The client transport shares a single HPACK encoder across every RPC on a
connection, so the encoder's dynamic table state persists between requests.
grpc-timeout carries the remaining time until the deadline, so its value is
effectively unique on every RPC.

Adding such a value to the HPACK dynamic table never yields a compression hit on
a later request: the value is different every time. It only costs a map insert
per RPC and, once the 4KB table fills, evicts genuinely reusable entries such as
content-type and :authority, which then have to be re-added. Marking the field
as sensitive keeps the encoder from indexing it, which lowers CPU spent in the
encoder and keeps the surrounding reusable fields from being evicted.

An isolated encode benchmark (single reused encoder, fresh grpc-timeout per
iteration, Apple M4) shows the encode path getting faster once grpc-timeout is
no longer indexed:

metadata fields   indexed      never-indexed   delta
0                 ~380 ns/op   ~294 ns/op       -23%
4                 ~498 ns/op   ~416 ns/op       -16%
12                ~765 ns/op   ~697 ns/op        -9%

The sensitive value is still Huffman-encoded, so the bytes on the wire for the
value itself are unchanged; only the dynamic-table entry is dropped. The
"never indexed" literal representation is standard HPACK (RFC 7541 §6.2.3) and
is decoded by any compliant peer.

RELEASE NOTES:

  • transport: reduce client CPU by not adding the per-RPC-unique grpc-timeout
    header to the HPACK dynamic table

@linux-foundation-easycla

linux-foundation-easycla Bot commented Aug 25, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: doroshenkosa / name: Sergey Doroshenko (9a2d432)

@doroshenkosa
doroshenkosa force-pushed the transport-hpack-never-index-unique-headers branch from 18afaca to 9a2d432 Compare August 25, 2026 20:14
…ader

The client transport shares a single HPACK encoder across every RPC on a
connection, so the encoder's dynamic table state persists between requests.
grpc-timeout carries the remaining time until the deadline, so its value is
effectively unique on every RPC.

Adding such a value to the HPACK dynamic table never yields a compression hit on
a later request: the value is different every time. It only costs a map insert
per RPC and, once the 4KB table fills, evicts genuinely reusable entries such as
content-type and :authority, which then have to be re-added. Marking the field
as sensitive keeps the encoder from indexing it, which both lowers CPU spent in
the encoder and improves the compression ratio of the surrounding, reusable
fields.

An isolated encode benchmark (single reused encoder, fresh grpc-timeout per
iteration, Apple M4) shows the encode path getting faster once grpc-timeout is
no longer indexed:

    metadata fields   indexed      never-indexed   delta
    0                 ~380 ns/op   ~294 ns/op       -23%
    4                 ~498 ns/op   ~416 ns/op       -16%
    12                ~765 ns/op   ~697 ns/op        -9%

The sensitive value is still Huffman-encoded, so the bytes on the wire for the
value itself are unchanged; only the dynamic-table entry is dropped. The
"never indexed" literal representation is standard HPACK (RFC 7541 6.2.3) and is
decoded by any compliant peer.
@doroshenkosa
doroshenkosa force-pushed the transport-hpack-never-index-unique-headers branch from 9a2d432 to 6f166ea Compare August 25, 2026 20:27
@eshitachandwani eshitachandwani self-assigned this Aug 31, 2026
@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.52%. Comparing base (93e31b4) to head (6f166ea).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9377      +/-   ##
==========================================
+ Coverage   87.47%   87.52%   +0.04%     
==========================================
  Files         425      425              
  Lines       30303    30303              
==========================================
+ Hits        26508    26522      +14     
+ Misses       3794     3780      -14     
  Partials        1        1              
Files with missing lines Coverage Δ
internal/transport/http2_client.go 94.86% <100.00%> (+0.30%) ⬆️

... and 25 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@eshitachandwani eshitachandwani added this to the 1.85 Release milestone Aug 31, 2026
@eshitachandwani eshitachandwani added the Type: Feature New features or improvements in behavior label Aug 31, 2026
@eshitachandwani

Copy link
Copy Markdown
Member

Hey @doroshenkosa , thank you for making this change! I am discussing this internally with the other maintainers to align on the best approach, and I will get back to you soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Feature New features or improvements in behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants