chengxis-mdb opened a new pull request, #16394: URL: https://github.com/apache/lucene/pull/16394
### Description <!-- If this is your first contribution to Lucene, please make sure you have reviewed the contribution guide. https://github.com/apache/lucene/blob/main/CONTRIBUTING.md --> #14701 rewrote `MaxScoreBulkScorer` window scoring from doc-at-a-time to term-at-a-time, draining essential clauses through `Scorer#nextDocsAndScores`. `TermScorer` got a bulk implementation over postings (#14709), but `ConstantScoreScorer` still uses the default one-`nextDoc()`-per-match loop. When the constant-score clause wraps a disjunction (e.g. what a `TermInSetQuery` rewrites to below the boolean-rewrite threshold), every `nextDoc()` pays a `DisiPriorityQueue` update. With tied constant scores across clauses the top-k threshold stalls and cannot prune, so the entire candidate stream pays the heap maintenance — profiles of an affected workload show ~35% of CPU in `DisiPriorityQueueN#updateTop`/`downHeap`, all under the term-at-a-time paths. This change makes `ConstantScoreScorer#nextDocsAndScores` drain a 4096-doc window (matching `MaxScoreBulkScorer.INNER_WINDOW_SIZE`) in bulk via `DocIdSetIterator#intoBitSet` and flatten it with `FixedBitSet#intoArray`. `DisjunctionDISIApproximation` implements `intoBitSet` with one bulk load per sub-iterator and no heap operations, which is exactly the shape that regresses. The bulk path is gated on the underlying iterator being a `DisjunctionDISIApproximation`. For iterators that are cheap to advance one doc at a time (a single postings list, a materialized bit set from a point query), the per-window fixed cost of the bulk path (bit set clear + flatten) exceeds the scalar loop it replaces — we measured this end-to-end, see the benchmark comment. Two-phase iterators keep the verified doc-at-a-time loop. The existing `intoBitSet` forwarding in the TOP_SCORES `DocIdSetIteratorWrapper` gets a guard for the delegate swap done by `setMinCompetitiveScore`: the new bulk path makes that scenario reachable, and the unguarded forwarding would call `intoBitSet` on an unpositioned empty iterator. Benchmark results (luceneutil, including a new constant-score disjunction task) posted in the comments. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
