okhttp: optimize HPACK to index :path and fix dynamic table eviction#12907
Open
AgraVator wants to merge 2 commits into
Open
okhttp: optimize HPACK to index :path and fix dynamic table eviction#12907AgraVator wants to merge 2 commits into
AgraVator wants to merge 2 commits into
Conversation
…bugs (grpc#12819) Allow the :path pseudo-header to be added to the HPACK dynamic table in the gRPC-Java OkHttp transport, resolving the original goal of grpc#12819 and redoing reverted commit 397d3e7 (grpc#12799, grpc#12820). Background & Root Cause: In gRPC over HTTP/2, :path headers represent static service/method names (e.g., /package.Service/Method), which are constant across RPC calls. Previously, indexing :path was reverted (grpc#12820) because high dynamic table churn uncovered latent bugs in legacy OkHttp Hpack.java: 1. Off-by-one NPE loop bound in evictToRecoverBytes: When bytesToRecover exceeded total dynamic table size, the loop condition (j >= nextDynamicTableIndex) inspected the unallocated nextDynamicTableIndex slot containing null, throwing a NullPointerException. Fixed by changing the loop bound to (j > nextDynamicTableIndex). 2. Reference leak post-eviction: System.arraycopy shifted active entries rightward, but left stale Header/ByteString references in vacated array slots. Fixed by setting vacated array slots to null via Arrays.fill(). 3. Case sensitivity normalization: Header entries inserted into dynamicTable are now guaranteed to store lowercased name keys, preventing failed dynamic table header lookups. 4. Table Size Setting Handling: Works in conjunction with grpc#12818 (SETTINGS_HEADER_TABLE_SIZE handling). Fixes grpc#12819 Related: grpc#12799, grpc#12818, grpc#12820, b/514688016
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.
Background & Problem Statement
In gRPC over HTTP/2, the
:pathpseudo-header represents static RPC service/method names (e.g.,/package.Service/Method), which remain constant across calls on long-lived channels.Indexing
:pathin HPACK's dynamic table reduces header transmission overhead from ~40+ bytes per RPC down to a single 1-byte indexed header field (0x80 | index).PR #12799 (commit
397d3e7214) originally enabled:pathindexing, but was reverted in PR #12820 (commit52f2cd5982) because continuous dynamic table insertions and evictions uncovered latent bugs in OkHttp's legacyHpack.javaimplementation during internal Google testing (b/514688016).This PR resolves tracking issue #12819 by fixing the underlying
Hpack.javadynamic table bugs and safely re-enabling:pathindexing.Changes Included in This PR
Fix Off-by-One NPE Loop Bound in
evictToRecoverBytes:Hpack.ReaderandHpack.Writer, whenbytesToRecoverexceeded total table byte count,j >= nextDynamicTableIndexevaluated slotnextDynamicTableIndex(which containsnull), throwing aNullPointerException.j > nextDynamicTableIndex.Garbage Collection Memory Leak Cleanup:
System.arraycopyshifted active elements rightward during eviction, but left staleHeader/ByteStringreferences in vacated array slots.Arrays.fill(dynamicTable, oldNext + 1, oldNext + 1 + entriesToEvict, null);post-arraycopyto sever hard references and enable GC.Normalized Header Casing in Dynamic Table:
dynamicTableare now guaranteed to store lowercasednamekeys (new Header(name, value)), preventing dynamic table key lookup mismatches.Re-enabled
:pathPseudo-Header Indexing:Writer.writeHeadersto allow both:authorityand:pathto be incrementally indexed in the HPACK dynamic table.Unit Tests:
HpackTest.javato test:pathindexing reuse (pseudoHeaderIndexingForPathAndAuthority) and addedevictToRecoverBytesDoesNotNpeWhenBytesToRecoverExceedsTable.Issue References
b/514688016