Open
Conversation
8646c87 to
b2b6c29
Compare
…n TOP_SCORES mode In PhraseScorer.TwoPhaseIterator.matches(), move matcher.reset() after the competitive score check so that non-competitive documents skip the expensive reset work entirely. reset() calls PostingsEnum.freq() which decodes a full PFOR block per term, plus initialises position iteration state (and for sloppy phrases, rebuilds a priority queue). Skipping this for documents whose maximum possible score is below minCompetitiveScore avoids significant wasted work. To support calling maxFreq() before reset(), both ExactPhraseMatcher and SloppyPhraseMatcher now load term frequencies eagerly inside maxFreq() and track this via a boolean flag. When reset() sees freqs are already loaded, it skips redundant freq() calls. When maxFreq() was not called (non-TOP_SCORES mode, or before minCompetitiveScore is established), reset() follows the original single-loop code path with zero added overhead. Also improves the JMH benchmark parameters (3 forks, 5 warmup iterations, 5s measurement intervals) for more statistically reliable results.
b2b6c29 to
ce9e8f5
Compare
Contributor
|
This PR has not had activity in the past 2 weeks, labeling it as stale. If the PR is waiting for review, notify the dev@lucene.apache.org list. Thank you for your contribution! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Optimise PhraseScorer by short-circuiting non-competitive documents in
TOP_SCORESmode.In
PhraseScorer.TwoPhaseIterator.matches(), thematcher.reset()call is moved after the competitive score check. This allows skipping the expensivereset()work for documents whose maximum possible score falls belowminCompetitiveScore.Why this matters
reset()is expensive because it:PostingsEnum.freq()which decodes a full PFOR block per term (seeLucene104PostingsReader)initPhrasePositions()By checking
maxFreq()first and short-circuiting when the document can't be competitive, all of this work is avoided.Implementation
To support calling
maxFreq()beforereset(), bothExactPhraseMatcherandSloppyPhraseMatchernow load term frequencies eagerly insidemaxFreq()and track this via aboolean freqsLoadedflag:reset()seesfreqsLoaded == true(maxFreq was called), it skips redundantfreq()callsmaxFreq()was not called (non-TOP_SCORESmode, or beforeminCompetitiveScoreis established),reset()follows the original single-loop code path with zero added overheadThe boolean flag approach avoids the cost of a virtual
approximation.docID()call that would be needed with alastDocIdguard.Testing
org.apache.lucene.search.*tests passTestPhraseMatcherContract: directly tests thatmaxFreq()can be called beforereset()for both exact and sloppy matchersPhraseScorerBenchmark) with 3 forks, 5 warmup iterations, 5s measurement intervalsBenchmarking
JMH benchmark (1M docs, 0.1% phrase matches, 50% docs with terms but no phrase):