Skip to content

Improve hnsw on heap ram est#14765

Merged
benwtrent merged 9 commits intoapache:mainfrom
benwtrent:improve-hnsw-on-heap-ram-est
Jun 11, 2025
Merged

Improve hnsw on heap ram est#14765
benwtrent merged 9 commits intoapache:mainfrom
benwtrent:improve-hnsw-on-heap-ram-est

Conversation

@benwtrent
Copy link
Member

@benwtrent benwtrent commented Jun 9, 2025

This makes OnHeapGraph builder RAM estimates much cheaper by incrementally updating the estimate as nodes are added to the NeighborArray.

Local benchmarking shows almost no performance impact, but I can no longer see any ram estimate methods in the top methods given the CPU samples.

One outstanding bit here is that OnHeapGraph#graphRamBytesUsed is only volatile. So, its not really threadsafe for estimates. However, from what I can tell, the only time we actually use this is during initial flush, and that is within a single thread anyways, right?

Follow on from: #14527

related: #14763

@github-actions
Copy link
Contributor

github-actions bot commented Jun 9, 2025

This PR does not have an entry in lucene/CHANGES.txt. Consider adding one. If the PR doesn't need a changelog entry, then add the skip-changelog label to it and you will stop receiving this reminder on future updates to the PR.

@mikemccand
Copy link
Member

Local benchmarking shows almost no performance impact, but I can no longer see any ram estimate methods in the top methods given the CPU samples.

Whoa, thank you for the quick PR @benwtrent! That's disappointing that there's no speedup on local benchmark, odd. I wonder if the nightly profiler (JFR) is somehow giving ghosts ... it should be async (no safepoint bias)? Or maybe it's an env/benchy difference and once we merge this we'll maybe see gains in the nightly benchy.

@mikemccand
Copy link
Member

Hmm, not sure it matters, but the JFR result I linked to in #14763 was from the single-threaded (deterministic, SerialMergeScheduler, takes forever) indexing run. I don't think it should matter ... that shouldn't cause unusual profiler ghosts.

Copy link
Member

@mikemccand mikemccand left a comment

Choose a reason for hiding this comment

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

I like this incremental approach instead! I was confused on whether we are missing some tracking in that base RAM_BYTES_USED.

I think your reasoning about thread safety is correct (we only track RAM during initial flush, and that is single threaded). Let's at least add comment / javadoc somewhere that explains this precarious thread safety situation? Who knows maybe someday IndexWriter will need to account for RAM consumed by merging...

// see: https://github.com/apache/lucene/issues/14214
// connectComponents();
frozen = true;
hnsw.finishBuild();
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, why remove this?

Copy link
Member Author

Choose a reason for hiding this comment

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

@mikemccand its not used. It was only added for the RAM estimate added in the previous PR. Since we are doing incremental updates, I just removed it.

private static final long RAM_BYTES_USED =
4L * Integer.BYTES // all int fields
+ 1 // field: noGrowth
+ RamUsageEstimator.NUM_BYTES_OBJECT_REF
Copy link
Member

Choose a reason for hiding this comment

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

Is this for the graph pointer we hold?

Copy link
Member Author

Choose a reason for hiding this comment

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

I am switching all of this to a simple RamUsageEstimator.shallowSizeOfInstance(OnHeapHnswGraph.class); attempting to account for fields directly is just too complicated

@benwtrent benwtrent requested a review from mikemccand June 10, 2025 15:14
IllegalArgumentException.class, () -> HnswGraphBuilder.create(scorerSupplier, 10, 0, 0));
}

@com.carrotsearch.randomizedtesting.annotations.Repeat(iterations = 100)
Copy link
Contributor

Choose a reason for hiding this comment

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

leftover, or intentional ?

Copy link
Member Author

Choose a reason for hiding this comment

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

LOL, of course, I want CI to REALLY exercise this test ;)

Copy link
Contributor

Choose a reason for hiding this comment

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

you can always override this locally by adding "-Ptests.iters=100".

Copy link
Contributor

@ChrisHegarty ChrisHegarty left a comment

Choose a reason for hiding this comment

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

LGTM

@ChrisHegarty ChrisHegarty modified the milestones: 10.3.0, 9.12.2 Jun 11, 2025
@github-actions github-actions bot modified the milestones: 9.12.2, 10.3.0 Jun 11, 2025
@benwtrent benwtrent merged commit 15987ee into apache:main Jun 11, 2025
7 checks passed
@benwtrent benwtrent deleted the improve-hnsw-on-heap-ram-est branch June 11, 2025 17:02
benwtrent added a commit that referenced this pull request Jun 11, 2025
* Disable HNSW connectedComponents (#14214)

* Adjusting OnHeapHnswGraph RAM estimation to be incremental during build

* changes

* addressing pr comments

* removing extra logging
@weizijun
Copy link
Contributor

@benwtrent Thanks for helping improve OnHeapGraph#graphRamBytesUsed!

benwtrent added a commit that referenced this pull request Jun 12, 2025
* Disable HNSW connectedComponents (#14214)

* Adjusting OnHeapHnswGraph RAM estimation to be incremental during build

* changes

* addressing pr comments

* removing extra logging
benwtrent added a commit that referenced this pull request Jun 12, 2025
* Disable HNSW connectedComponents (#14214)

* Adjusting OnHeapHnswGraph RAM estimation to be incremental during build

* changes

* addressing pr comments

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants