Skip to content

chore: Migrate cross-product lookups to use bitmask isntead of CommutativeDuplex - BED-8362#2821

Open
StephenHinck wants to merge 2 commits into
mainfrom
BED-8362
Open

chore: Migrate cross-product lookups to use bitmask isntead of CommutativeDuplex - BED-8362#2821
StephenHinck wants to merge 2 commits into
mainfrom
BED-8362

Conversation

@StephenHinck
Copy link
Copy Markdown
Contributor

@StephenHinck StephenHinck commented May 26, 2026

Description

Migrates CalculateCrossProductNodeSets to utilize a bitmap instead of CommutativeDuplex for performance optimization. In pathological cases, this resulted in a 98% reduction in post-processing time for ADCS.

Motivation and Context

Resolves BED-8362

Why is this change required? What problem does it solve?

How Has This Been Tested?

Existing test suites are unchanged. Additionally, performed manual validation utilizing several local datasets.

Screenshots (optional):

Types of changes

  • Chore (a change that does not modify the application functionality)

Checklist:

Summary by CodeRabbit

  • Refactor
    • Optimized cross-product computation by switching to aggregated bitmap-based membership checks.
    • Replaced per-element iteration with bulk bitmap intersections and unions, reducing iteration overhead.
    • Updated internal handling of reference sets and remainder merging for more efficient set operations, improving runtime and resource usage.

Review Change Stack

@StephenHinck StephenHinck self-assigned this May 26, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

📝 Walkthrough

Walkthrough

CalculateCrossProductNodeSets in ad.go is refactored to precompute a materialized check set bitmap through OR and AND operations across nodesets, replacing lazy construction. This materialized set is then used for membership checks and to optimize the final result iteration through bitmap intersection rather than element-by-element filtering.

Changes

Eager Check Set Materialization

Layer / File(s) Summary
Materialized check set construction and first use
packages/go/analysis/ad/ad.go
Introduces materializedCheckSet by OR-ing unrolled bitmaps within each nodeset and AND-ing across nodesets, then uses it for firstDegreeSets[0] membership evaluation to replace lazy checkSet logic.
Check set consumption and supporting updates
packages/go/analysis/ad/ad.go
Updates the unrolledRefSet comment for clarity, applies materializedCheckSet to group-match conditionals, and replaces remainder iteration with direct bitmap intersection followed by union into result entities.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels: go

Suggested reviewers:

  • superlinkx
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description includes all major required sections: Description, Motivation and Context (with Jira ticket reference), How Has This Been Tested, Types of changes, and a completed Checklist confirming prerequisites and test practices were followed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The PR title mentions migrating cross-product lookups to use bitmask, which aligns with the core change described in the summary (replacing checkSet logic with materializedCheckSet bitmap). However, the title contains a typo ('isntead' instead of 'instead') and references 'CommutativeDuplex' which is not explicitly mentioned in the code summary, creating slight ambiguity about the exact technical details being replaced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch BED-8362

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/go/analysis/ad/ad.go (1)

618-624: 💤 Low value

Consider reusing setUnion bitmap across iterations.

A new bitmap is allocated each iteration. Since setUnion is discarded after each And operation, you could hoist the allocation and call Clear() at the start of each iteration to reduce GC pressure in pathological cases with many nodesets.

♻️ Suggested optimization
+	setUnion := cardinality.NewBitmap64()
 	for _, unrolledSet := range unrolledSets[2:] {
-		setUnion := cardinality.NewBitmap64()
+		setUnion.Clear()
 		for _, bm := range unrolledSet {
 			setUnion.Or(bm)
 		}
 		materializedCheckSet.And(setUnion)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/go/analysis/ad/ad.go` around lines 618 - 624, The loop repeatedly
allocates a new bitmap via cardinality.NewBitmap64() for setUnion; instead,
allocate setUnion once before iterating over unrolledSets[2:], and inside the
loop call setUnion.Clear() before OR-ing each bm, then use
materializedCheckSet.And(setUnion) as before—this reuses the same bitmap
instance (referencing variables unrolledSets, setUnion, materializedCheckSet and
the constructor cardinality.NewBitmap64) to reduce GC pressure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/go/analysis/ad/ad.go`:
- Around line 618-624: The loop repeatedly allocates a new bitmap via
cardinality.NewBitmap64() for setUnion; instead, allocate setUnion once before
iterating over unrolledSets[2:], and inside the loop call setUnion.Clear()
before OR-ing each bm, then use materializedCheckSet.And(setUnion) as
before—this reuses the same bitmap instance (referencing variables unrolledSets,
setUnion, materializedCheckSet and the constructor cardinality.NewBitmap64) to
reduce GC pressure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 7be73307-5588-46a8-9d82-4ae436286ac0

📥 Commits

Reviewing files that changed from the base of the PR and between 916ea3d and d4d373a.

📒 Files selected for processing (1)
  • packages/go/analysis/ad/ad.go

@coderabbitai coderabbitai Bot added the go Pull requests that update go code label May 26, 2026
}

// This means that len(firstDegreeSets) must be greater than or equal to 2 i.e. we have at least two nodesets (unrolled) without Auth. Users/Everyone
checkSet.Or(cardinality.CommutativeOr(unrolledSets[1]...))
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.

I would like to understand the motivation behind #2364 before moving forward with this changeset. The commutative work was done fairly recently seemingly in response to observed bottlenecks that this changeset will undo.

Perhaps we need to have the code in place for both and pivot based on the graph shape instead of always doing or the other.

Copy link
Copy Markdown
Contributor

@urangel urangel May 27, 2026

Choose a reason for hiding this comment

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

After reviewing more closely I see that the contains check is where we currently have an excess of computation since we have to check every bitmap in the and slice for a commutative duplex. That combined with contains checks being done three times inside of different loops is way more processing than up front intersection that then benefits from direct contains checking with no additional looping. Nice

@StephenHinck StephenHinck changed the title chore: Migrate cross-product lookups to use bitmask isntead of CumulativeDuplex - BED-8362 chore: Migrate cross-product lookups to use bitmask isntead of CommutativeDuplex - BED-8362 May 26, 2026
checkSet.Or(cardinality.CommutativeOr(unrolledSets[1]...))
// Materialize the check set as a single bitmap by Or-ing all component bitmaps within each set, then And-ing across sets.
materializedCheckSet := cardinality.NewBitmap64()
for _, bm := range unrolledSets[1] {
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.

nit: The changeset is good but would appreciate updating bm to bitmap or set in this loop and the nested loop below for a bit more clarity


// This means that len(firstDegreeSets) must be greater than or equal to 2 i.e. we have at least two nodesets (unrolled) without Auth. Users/Everyone
checkSet.Or(cardinality.CommutativeOr(unrolledSets[1]...))
// Materialize the check set as a single bitmap by Or-ing all component bitmaps within each set, then And-ing across sets.
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.

nit: While Or and And should be understood given the context, the bitmap methods are named this way already so I suggest updating the comment here to spell out union and intersection so that it adds more insight than seeing the code itself.

Suggested change
// Materialize the check set as a single bitmap by Or-ing all component bitmaps within each set, then And-ing across sets.
// Materialize the check set as a single bitmap from the union of all component bitmaps (`Or`) within each set, then intersecting (`And`) across sets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants