Skip to content

Add TaxonomyReader#getBulkOrdinals method (#12180) - #12769

Merged
mikemccand merged 1 commit into
apache:mainfrom
epotyom:faceting-getBulOrdinals
Nov 9, 2023
Merged

mikemccand merged 1 commit into
apache:mainfrom
epotyom:faceting-getBulOrdinals

Conversation

@epotyom

@epotyom epotyom commented Nov 6, 2023

Copy link
Copy Markdown
Contributor

Add TaxonomyReader#getBulkOrdinals method (#12180)

This is the first step for #12180 , next step will be to implement Facets#getSpecificValues (bulk) that calls getBulkOrdinals, will do it in a separate PR.

@mikemccand mikemccand left a comment •

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.

This looks great @epotyom - I left some small comments.

I wonder what performance impact this might have for heavy Lucene facet use cases... but we don't need to block this nice API with specific benchmarking. It can come later. Maybe we could (later) fix Lucene's nightly benchmark in luceneutil for faceting tasks to use this new API... maybe open an issue there?

private void assertGettingPaths(
DirectoryTaxonomyReader reader, FacetLabel[] expectedPaths, int[] sourceOrds)
throws IOException {
// To exercise mix of cache hit and cache misses for getPath and getBulkPath this method:

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.

Cool!

src.close();
}

private void assertGettingOrdinals(

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 we maybe add a thread safety test as well, if we aren't already testing across threads? Index many FacetLabel -> ord, open reader, spawn threads all doing random lookups and confirming the ords are correct? Maybe with random cache sizes so we sometimes face evictions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is testCallingBulkPathReturnsCorrectResult test (I renamed it to testGetPathAndOrdinalsRandomMultithreading) which runs multiple threads. It used to only call getBulkPath, I changed it to use assertPathsAndOrdinals, which means that each thread somewhat randomly calls getPath, getBulkPath, getOrdinal and the new getBulkOrdinals. But maybe we can improve it:

  1. It creates an array of 1K random facets, and the cache size DEFAULT_CACHE_VALUE is 4K, so there are no evictions AFAIU. I can change the array size to something like 10K to sometimes cause evictions.
  2. I'm not sure if calling all 4 methods in test threads is the right thing to do as it reduces chances for "collisions" e.g. calling getBulkPath and getBulkOrdinals in parallel is unlikely to reveal any issues because these 2 methods use different cache instances, etc. I think I can split into 2 tests: one to randomly call getPath+getBulkPath in multiple threads, and another one to do the same for getOrdinal+getBulkOrdinals?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Pushed the branch with the changes, please review!

* found.
*/
public int[] getBulkOrdinals(FacetLabel... categoryPath) throws IOException {
int[] ords = new int[categoryPath.length];

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.

I love the above javadoc, but maybe additionally add comment here that this is the simple & slow base class / default implementation, and note that DirectoryTaxonomyReader has an optimized and more complex version?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will do!

@epotyom

epotyom commented Nov 6, 2023

Copy link
Copy Markdown
Contributor Author

Thank you for reviewing @mikemccand !

I wonder what performance impact this might have for heavy Lucene facet use cases... but we don't need to block this nice API with specific benchmarking. It can come later. Maybe we could (later) fix Lucene's nightly benchmark in luceneutil for faceting tasks to use this new API... maybe open an issue there?

I can make sure that we have a task that calls this method (indirectly) in the next step for this issue - adding bulk Facets#getSpecificValues, will that be ok?

@epotyom
epotyom force-pushed the faceting-getBulOrdinals branch from 6c40956 to 7384fea Compare November 7, 2023 17:44
@epotyom
epotyom force-pushed the faceting-getBulOrdinals branch from 7384fea to dc943c5 Compare November 8, 2023 10:52
@mikemccand

Copy link
Copy Markdown
Member

I can make sure that we have a task that calls this method (indirectly) in the next step for this issue - adding bulk Facets#getSpecificValues, will that be ok?

+1, thanks!

@mikemccand mikemccand left a comment

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.

Looks great, thank you @epotyom -- I'll merge.

String randomArray[] = new String[RandomizedTest.randomIntBetween(1, 1000)];
final int maxNumberOfLabelsToIndex = 1000;
final int maxNumberOfUniqueLabelsToIndex = maxNumberOfLabelsToIndex / 2;
final int cacheSize = maxNumberOfUniqueLabelsToIndex / 2; // to cause some cache evictions

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.

Thanks!

@mikemccand
mikemccand merged commit fb5f491 into apache:main Nov 9, 2023
@mikemccand

Copy link
Copy Markdown
Member

I think this is safe to backport to 9.x? I'll do that, and move the CHANGES.txt entry down.

@uschindler

Copy link
Copy Markdown
Contributor

Hi, the commit causes test failures like this from time to time:

org.apache.lucene.facet.taxonomy.directory.TestDirectoryTaxonomyReader > testGetPathAndOrdinalsRandomMultithreading FAILED
    com.carrotsearch.randomizedtesting.UncaughtExceptionError: Captured an uncaught exception in thread: Thread[id=276, name=Thread-152, state=RUNNABLE, group=TGRP-TestDirectoryTaxonomyReader]

        Caused by:
        java.lang.IllegalArgumentException: bound must be positive
            at __randomizedtesting.SeedInfo.seed([EB36AAC7E6947189]:0)
            at java.base/java.util.Random.nextInt(Random.java:322)
            at randomizedtesting.runner@2.8.1/com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom.nextInt(Xoroshiro128PlusRandom.java:73)
            at randomizedtesting.runner@2.8.1/com.carrotsearch.randomizedtesting.AssertingRandom.nextInt(AssertingRandom.java:87)
            at org.apache.lucene.facet.taxonomy.directory.TestDirectoryTaxonomyReader.assertGettingPaths(TestDirectoryTaxonomyReader.java:519)
            at org.apache.lucene.facet.taxonomy.directory.TestDirectoryTaxonomyReader$4.run(TestDirectoryTaxonomyReader.java:721)

And hundreds of more threads following. Looks like sometimes the ordinals array is initialized by zero length. The followup random then fail because the upper bound passed to random#nextInt(limit) must be limit>=1.

@uschindler

Copy link
Copy Markdown
Contributor

Looks like the ordinals array sizes must be at least 1, so in general the initial setup of the ordinal size must use numOrdinals = random(limit) + 1;

@mikemccand

mikemccand commented Nov 9, 2023 via email

Copy link
Copy Markdown
Member

@epotyom

epotyom commented Nov 9, 2023 via email

Copy link
Copy Markdown
Contributor Author

}
}
// all ordinals found in cache
if (indexesMissingFromCache.length == 0) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

With AI pocking around the code, I found that this condition never passes.
Fix: #16783

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.

4 participants