Skip to content

base: shrink the code FlatHashMapV2 generates - #7853

Merged
LalitMaganti merged 1 commit into
mainfrom
dev/lalitm/fhm-v2-code-size
Oct 9, 2026
Merged

LalitMaganti merged 1 commit into
mainfrom
dev/lalitm/fhm-v2-code-size

Conversation

@LalitMaganti

@LalitMaganti LalitMaganti commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Summary

Cuts the code FlatHashMapV2 generates per call site to under what
FlatHashMapV1 generates, without slowing down inserts.

Why

FlatHashMapV2 force-inlined its whole probe loop into every Find() and
Insert(): ~750 bytes of code per insert+find call site vs ~150 for
FlatHashMapV1. Moving code over to it, which is otherwise faster, would
have grown binaries by hundreds of KB.

Changes

  • Insert() inlines only constructing the key and value. Finding or
    claiming the slot is out of line in FindOrPrepareInsert(), compiled
    once per key type. Find() is out of line too.
  • The state and the operations which don't depend on the key and value
    types (allocating, growing, probing for a free slot) move to an
    untemplated FlatHashMapV2Base, shared by all maps, defined in the
    new src/base/flat_hash_map.cc.
  • Rehashing moves entries straight into their new slots, rather than
    through Insert().
  • Lookups work as in absl: Find(), Erase(), Insert() and
    operator[] take a Key, which the caller converts to, and only a
    transparent Hasher enables other (heterogeneous) key types.
    MurmurHash is now transparent only for string-like keys: it also was
    for integers, hashing an int looked up in a map keyed by uint32_t
    as an int, so e.g. a negative one could miss (in FlatHashMapV1 too).

Benchmarks

Code size for 16 map types (x64, -O3):

1 site per type 8 sites per type Per insert+find site
FlatHashMapV1 26.9 KB 44.0 KB ~150 B
FlatHashMapV2 before 37.3 KB 121.1 KB ~750 B
FlatHashMapV2 after ~27 KB ~35 KB ~80 B

Speed, flat_hash_map_benchmark on Linux x64: inserts are unchanged.
Lookups through the out of line Find() are 4-14% slower than before,
still ~1.7x faster than FlatHashMapV1.

Testing

FlatHashMap* and MurmurHash* unit tests, with one test changed to
construct its Key (an int is no longer a heterogeneous key for it) and
one added for MurmurHash's transparency. A trace processor build moved
onto this (in the follow-up PR) gives the same query results on three
traces.

@LalitMaganti
LalitMaganti requested a review from a team as a code owner October 8, 2026 21:40
@LalitMaganti
LalitMaganti added this pull request to stack #7855 October 8, 2026 21:42
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/fhm-v2-code-size branch 4 times, most recently from a7180ab to db2a9a3 Compare October 8, 2026 23:10

@safayat-google safayat-google left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks Great!

Just few nits.

Comment thread src/base/murmur_hash_unittest.cc
Comment thread include/perfetto/ext/base/flat_hash_map.h Outdated
Comment thread src/base/flat_hash_map_unittest.cc Outdated
Comment thread src/base/flat_hash_map.cc Outdated
FlatHashMapV2 inlined its whole probe loop into every Find() and Insert()
call site, costing ~750 bytes of code per insert+find site vs ~150 for
FlatHashMapV1, so moving code over to it would have grown binaries.

Insert() now inlines only constructing the key and value; finding or
claiming the slot is out of line in FindOrPrepareInsert(), compiled once
per key type, as is Find(). The state and the operations which don't
depend on the key and value types (allocating, growing, probing for a
free slot) move to an untemplated FlatHashMapV2Base, defined in
flat_hash_map.cc and shared by all maps, and rehashing moves entries
straight into their new slots rather than going through Insert().

Lookups now work as in absl: Find(), Erase(), Insert() and operator[]
take a Key, which the caller converts to, and only a transparent Hasher
enables other (heterogeneous) key types. MurmurHash is now transparent
only for string-like keys: it also was for integers, hashing an int
looked up in a map keyed by uint32_t as an int, so e.g. a negative one
could miss. Each heterogeneous key type also compiled the probing again.

For 16 map types with 8 insert+find sites each (x64): 121KB -> 35KB of
code, vs 44KB for FlatHashMapV1. Inserts are unchanged; lookups through
the out of line Find() are 4-14% slower in microbenchmarks.
@LalitMaganti
LalitMaganti force-pushed the dev/lalitm/fhm-v2-code-size branch from db2a9a3 to 3a26150 Compare October 9, 2026 16:54
@LalitMaganti
LalitMaganti merged commit 152b09b into main Oct 9, 2026
27 checks passed
@LalitMaganti
LalitMaganti deleted the dev/lalitm/fhm-v2-code-size branch October 9, 2026 16:56
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.

2 participants