Skip to content

(protobuf) Fix EnumLookup hash-area sizing - #773

Open
pjfanning wants to merge 1 commit into
FasterXML:3.xfrom
pjfanning:protobuf-enum-lookup-sizing
Open

(protobuf) Fix EnumLookup hash-area sizing#773
pjfanning wants to merge 1 commit into
FasterXML:3.xfrom
pjfanning:protobuf-enum-lookup-sizing

Conversation

@pjfanning

Copy link
Copy Markdown
Member

Split out of #772.

LinkedHashMap<Integer,String> byId = new LinkedHashMap<Integer,String>();

// First: calculate size of primary hash area
final int size = findSize(byId.size());

byId is created on the line above and populated in the loop below, so this is always findSize(0) == 8. Every protobuf enum, regardless of size, got an 8-slot primary + 4-slot secondary hash area. A 100-value enum pushed ~88 entries into the linearly-scanned spill area, and grew the backing arrays 4 slots at a time while building it.

Sizing from entries instead gives 128 primary slots and 19 spills for the same enum.

Correctness was never affected — the spill scan finds everything — so this is purely lookup and construction cost, paid on every enum-valued field write.

Pre-dates the 2.x -> 3.x rename and is present on 2.21 too; targeting 3.x for now, happy to redo against 2.21 and merge forward if you prefer.

Test

EnumLookupTest — a 100-value enum resolves every entry by name and by index, and the primary hash area is 128 slots rather than 8. Needed two package-private accessors (hashArea(), spillCount()) on EnumLookup.Big.

Full protobuf module test suite passes.

🤖 Generated with Claude Code

`EnumLookup.Big.construct()` called `findSize(byId.size())` on the line
after `byId` was created and before it was populated, so the result was
always `findSize(0)` == 8 regardless of enum size.

Every protobuf enum therefore got an 8-slot primary + 4-slot secondary
hash area. A 100-value enum pushed ~88 entries into the linearly-scanned
spill area, and grew the backing arrays 4 slots at a time while building
it. Sizing from `entries` gives 128 primary slots and 19 spills for the
same enum.

Correctness was never affected -- the spill scan finds everything -- but
the cost is paid on every enum-valued field write.

Adds a regression test, plus two package-private accessors on
`EnumLookup.Big` so the hash-area sizing can be asserted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

🧪 Code Coverage Report

Coverage Type Coverage Change
📝 Instructions 76.87% 📈 +0.21%
🔀 Branches 68.51% 📈 +0.25%

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.

1 participant