Skip to content

Replace bits-and-blooms/bitset with roaring bitmaps#2386

Open
ValentaTomas wants to merge 7 commits intomainfrom
replace-bitset-with-roaring
Open

Replace bits-and-blooms/bitset with roaring bitmaps#2386
ValentaTomas wants to merge 7 commits intomainfrom
replace-bitset-with-roaring

Conversation

@ValentaTomas
Copy link
Copy Markdown
Member

Replace all direct usage of bits-and-blooms/bitset with roaring/v2 (v2.17.0). Uses the new Ranges() iterator (#522) for range iteration in CreateMapping and BitmapRanges.

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 14, 2026

PR Summary

Medium Risk
Touches snapshot diff metadata/mapping generation and dirty-page tracking used to export rootfs/memory diffs, so a subtle bitmap semantic change could produce incorrect snapshot contents or sizes. The rest is mostly mechanical API migration plus a test timeout bump.

Overview
This PR migrates snapshot/memory/rootfs diff tracking from bits-and-blooms/bitset to roaring/v2 bitmaps, updating dirty/empty metadata types, range iteration to use Bitmap.Ranges(), and related callers/telemetry so diff export and mapping generation operate on roaring structures. It also updates module dependencies to pin roaring/v2 (via an e2b-dev/roaring replace) and increases the cgroup round-trip test timeout to reduce flakiness.

Reviewed by Cursor Bugbot for commit fa35957. Bugbot is set up for automated code reviews on this repo. Configure here.

@ValentaTomas ValentaTomas force-pushed the replace-bitset-with-roaring branch 6 times, most recently from fc7f1b4 to 0205899 Compare April 14, 2026 00:38
@ValentaTomas ValentaTomas marked this pull request as ready for review April 14, 2026 00:40
@ValentaTomas ValentaTomas force-pushed the replace-bitset-with-roaring branch from 6ec4c90 to b81ec2a Compare April 14, 2026 00:49
@ValentaTomas ValentaTomas force-pushed the replace-bitset-with-roaring branch from b81ec2a to b6fa8a5 Compare April 14, 2026 00:53
Use roaring v2.17.0 with the new Ranges() iterator throughout.
Remove bitset as a direct dependency.
@ValentaTomas ValentaTomas force-pushed the replace-bitset-with-roaring branch from b6fa8a5 to b0717ba Compare April 14, 2026 00:56
ValentaTomas and others added 3 commits April 13, 2026 22:37
Point roaring/v2 at e2b-dev/roaring@efficient-range-iteration until the
Ranges() iterator fix is merged upstream. This resolves CI failures from
the efficient range iteration implementation.
The process_dies_with_cgroups test gives 5s for the OOM killer to fire
after `sleep 1 && tail /dev/zero` with a 1MB memory limit. On ARM64
runners the OOM kill can take longer, causing the context to time out
before the process is killed. Increase to 15s.
@ValentaTomas ValentaTomas marked this pull request as draft April 14, 2026 06:10
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 405f3d0. Configure here.

@ValentaTomas ValentaTomas marked this pull request as ready for review April 14, 2026 07:13
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa35957fa3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


tool github.com/vektra/mockery/v3

replace github.com/RoaringBitmap/roaring/v2 => github.com/e2b-dev/roaring/v2 v2.16.1-0.20260414062913-60ea6a744802
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.

is this needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, waiting for them to merge my bugfix upstream.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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


return bitsetOffsets(t.b.Clone(), t.BlockSize())
}
snapshot := t.b.Clone()
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.

why do we need to clone here?

return &header.DiffMetadata{
Dirty: bitset.From(res.Payload.Resident),
Empty: bitset.From(res.Payload.Empty),
Dirty: roaring.FromDense(res.Payload.Resident, false),
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.

could you explain why with doCopy=false and why you don't call RunOptimize

Comment on lines +45 to +48
allPages := roaring.New()
allPages.AddRange(0, uint64(numberOfPages))

empty = empty.Difference(dirty)
empty := roaring.AndNot(allPages, dirty)
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.

wouldn't this work better?

Suggested change
allPages := roaring.New()
allPages.AddRange(0, uint64(numberOfPages))
empty = empty.Difference(dirty)
empty := roaring.AndNot(allPages, dirty)
empty := roaring.FlipInt(dirty, 0, uint64(numberOfPages))

}

dirty := diffInfo.Dirty.Difference(diffInfo.Empty)
dirty := roaring.AndNot(diffInfo.Dirty, diffInfo.Empty)
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.

use

Suggested change
dirty := roaring.AndNot(diffInfo.Dirty, diffInfo.Empty)
diffInfo.Dirty.AndNot(diffInfo.Empty)

to prevent allocating an extra bitmap

then in

header.DiffMetadata{
		Dirty:     diffInfo.Dirty,

Copy link
Copy Markdown
Contributor

@levb levb left a comment

Choose a reason for hiding this comment

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

a few nits, otherwise LGTM

}

maxTimeout := time.Second * 5
maxTimeout := time.Second * 15
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unrelated to the change, right?

}

diffMetadata := header.NewDiffMetadata(c.blockSize, c.dirty.BitSet())
diffMetadata := header.NewDiffMetadata(c.blockSize, c.dirty.Bitmap())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0/5 nit: Do we need to clone under the RLock here, or (since we are holding c.mu - maybe we can operate on dirty's data directly here?

}

return slices.Collect(b.EachSet())
result := make([]uint, 0, b.GetCardinality())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0/5 nit: This function is called only in tests, should it be moved there? I flagged the allocation, but it's fine for the use case.


roaring "github.com/RoaringBitmap/roaring/v2"
"github.com/bits-and-blooms/bitset"
"github.com/RoaringBitmap/roaring/v2"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0/5 now that it is always roaring and we intermix it with explicit roaring sets in the code, rename the package to syncroaring? the generic atomicbitset is no longer intention-revealing?

}

func (b *Bitset) BitSet() *bitset.BitSet {
func (b *Bitset) Bitmap() *roaring.Bitmap {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See my comment in ExportToDiff - I question the need to do this.

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.

3 participants