Repository navigation
Speed up Contains for 32-bit and 64-bit bitmaps - #587
Merged
Merged
Conversation
- Bitmap.Contains uses a type switch instead of an interface call, which also lets the bitmap-container test inline. - runContainer16.contains uses a dedicated branchless search over the interval starts instead of the general searchRange. - Key lookup in Contains (both packages) and arrayContainer.contains use a lower-bound search (no early exit on equality) finished by a linear scan. - Add BenchmarkContains and BenchmarkContains64.
1 task done
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.
This PR makes
Containsfaster in both the root package androaring64.Changes
Bitmap.Containsinstead of a dynamic interface call. This also lets the bitmap-container bit test inline.runContainer16.contains: a branchless search over interval starts, then a singlekey - start <= lengthcheck. Before, it went throughsearch→searchRange, which returns three values and counts comparisons.searchUint16, plus auint32version inroaring64): no early exit on equality (rarely taken, and it costs an extra branch per step), finished by a linear scan of the last 16 elements. It's used for the key lookup inContainsand inarrayContainer.contains. Other callers ofbinarySearchare unchanged.BenchmarkContainsandBenchmarkContains64.Results
Median ns/query, 4096 random queries (half hits, half misses), with the variants measured side by side in the same process. Hardware: Apple M4 Max (arm64) and Xeon Gold 6548N (amd64, pinned with
taskset).roaring64key search (8 to 16384 keys)No case was slower on either machine.
Not included
A fully branchless key and array search is another 30–50% faster on the Xeon but 50–70% slower on the M4. Go won't emit CMOV/CSEL for a value carried through the loop, so the branchless loop has to wait for each load in turn. That could be a follow-up in an amd64-only file with a generic fallback, after measuring on a Neoverse arm64 server.
go test ./...passes.