Skip to content

bitmap: use bits.LeadingZeros64 intrinsic in maximum()#529

Merged
lemire merged 1 commit into
RoaringBitmap:masterfrom
TheHippo:use-bits-LeadingZeros64
Jul 1, 2026
Merged

bitmap: use bits.LeadingZeros64 intrinsic in maximum()#529
lemire merged 1 commit into
RoaringBitmap:masterfrom
TheHippo:use-bits-LeadingZeros64

Conversation

@TheHippo

Copy link
Copy Markdown
Contributor

Description

bitmapContainer.maximum() finds the highest set bit by counting the leading zeros of the top word. It used a hand-written helper, clz(), to do that counting. This change makes it use the standard library's math/bits.LeadingZeros64 instead (already wrapped in this package as countLeadingZeros), and removes clz().

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Performance improvement
  • Code refactoring
  • Documentation update
  • Test improvements
  • Build/CI changes

Changes Made

What was changed?

  • bitmapContainer.maximum() now computes the highest set bit using countLeadingZeros(w) (i.e. math/bits.LeadingZeros64) instead of the private clz()` function.
  • The hand-rolled clz(i uint64) int helper in bitmapcontainer.go is deleted (it had no other callers).

Why was it changed?

clz() counted the leading zero bits of a word using a chain of if checks and bit shifts. The standard library already does the same thing with math/bits.LeadingZeros64, which the Go compiler turns into a single CPU instruction (LZCNT on amd64, CLZ on arm64). In short, clz() was a slower, handwritten version of something the standard library does in one instruction.

How was it changed?

  • Replaced clz() with countLeadingZeros() the body of maximum().
  • Removed the clz() function.

Testing

Passes. maximum() is exercised by the existing root-package tests (roaring_test.go) and the randomized property_test.go, which compare Maximum() against reference behavior over many bitmaps - these cover the substitution directly. No new test was required.

Fuzzing

Not affected by this change (no serialization/parsing surface is touched), but the existing fuzz harness continues to build and run.

Performance Impact

Negligible-to-positive.

Performance Analysis

benchstat reports a 3.58% improvement over the entire benchmark suite (geomean).

Breaking Changes

None. Public API and behavior are unchanged.

bitmapContainer.maximum() relied on a hand-rolled clz() to find the
highest set bit in the most significant non-empty word. That helper
reimplemented, in portable shift/compare arithmetic, what the standard
library already exposes as math/bits.LeadingZeros64, which the Go
compiler lowers to a single hardware instruction (LZCNT on amd64, CLZ on
arm64). The package already wraps it as countLeadingZeros (clz.go), so
maximum() now calls that and the redundant clz() helper is deleted.
@lemire lemire merged commit bd4128b into RoaringBitmap:master Jul 1, 2026
8 checks passed
@TheHippo TheHippo deleted the use-bits-LeadingZeros64 branch July 1, 2026 15:57
@TheHippo

TheHippo commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Just for the record / clarification:

the Go compiler turns into a single CPU instruction (LZCNT on amd64, CLZ on arm64)

  • The arm64 optimization always happens
  • The amd64 optimization only happens when compiled with GOAMD64=v3

@lemire

lemire commented Jul 2, 2026

Copy link
Copy Markdown
Member

@TheHippo Yes. I know. Thanks for the PR.

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