Skip to content

Shift before truncating block starts in binary_fuse8_populate (fixes #80) - #81

Merged
lemire merged 1 commit into
masterfrom
fix-issue-80-fuse8-startpos
Oct 30, 2026
Merged

lemire merged 1 commit into
masterfrom
fix-issue-80-fuse8-startpos

Conversation

@lemire

@lemire lemire commented Oct 30, 2026

Copy link
Copy Markdown
Member

Fixes #80.

binary_fuse8_populate cast i * size to 32 bits before shifting by blockBits, so the product wrapped once it reached 2^32 (from about 8.4M keys). Wrapped block starts land inside the low blocks, so placement walks many blocks before finding a free slot. The filter stayed correct, but populate got much slower. This applies the parenthesization already used in binary_fuse16_populate:

-      startPos[i] = (uint32_t)((uint64_t)i * size) >> blockBits;
+      startPos[i] = (uint32_t)(((uint64_t)i * size) >> blockBits);

At 20M keys (-O3, Apple silicon, one run), fuse8 populate goes from 120.9 ns/key to 27.2 ns/key, and every key is still contained. make unit && ./unit passes.

)

The cast to uint32_t was applied to i * size before the shift, so the
product wrapped above 2^32 (from about 8.4M keys) and block starts landed
in low positions, slowing populate several fold. Match the fuse16 code.
@lemire
lemire merged commit f6f09de into master Oct 30, 2026
12 checks passed
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.

binary_fuse8_populate truncates its block starts to 32 bits before the shift, slowing builds above 8.4M keys

1 participant