Index: lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java (revision 1531467) +++ lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java (working copy) @@ -332,7 +332,8 @@ // Check if we can and should return a BooleanScorer // TODO: (LUCENE-4872) in some cases BooleanScorer may be faster for minNrShouldMatch // but the same is even true of pure conjunctions... - if (!scoreDocsInOrder && topScorer && required.size() == 0 && minNrShouldMatch <= 1) { + // nocommit turn on + if (false && !scoreDocsInOrder && topScorer && required.size() == 0 && minNrShouldMatch <= 1) { return new BooleanScorer(this, disableCoord, minNrShouldMatch, optional, prohibited, maxCoord); } Index: lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java (revision 1531467) +++ lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java (working copy) @@ -31,6 +31,7 @@ protected double score = Float.NaN; private final float[] coord; + private final int[] matchQueue; /** Construct a DisjunctionScorer. * @param weight The weight to be used. @@ -44,6 +45,8 @@ throw new IllegalArgumentException("There must be at least 2 subScorers"); } this.coord = coord; + // nocommit I think +1 should be sufficient? + matchQueue = new int[subScorers.length+2]; } @Override @@ -69,26 +72,31 @@ final Scorer sub = subScorers[0]; doc = sub.docID(); if (doc != NO_MORE_DOCS) { + // TODO: this currently scores, but so did the previous impl + // TODO: if we separate scoring, out of here, + // then change freq() to just always compute it from scratch score = sub.score(); nrMatchers = 1; - countMatches(1); - countMatches(2); + matchQueue[0] = 1; + matchQueue[1] = 2; + int matchQueueSize = 2; + + while (matchQueueSize > 0) { + int root = matchQueue[matchQueueSize-1]; + if (root < numScorers && subScorers[root].docID() == doc) { + nrMatchers++; + score += subScorers[root].score(); + root = root << 1; + matchQueue[matchQueueSize-1] = root+1; + matchQueue[matchQueueSize] = root+2; + matchQueueSize++; + } else { + matchQueueSize--; + } + } } } - - // TODO: this currently scores, but so did the previous impl - // TODO: remove recursion. - // TODO: if we separate scoring, out of here, - // then change freq() to just always compute it from scratch - private void countMatches(int root) throws IOException { - if (root < numScorers && subScorers[root].docID() == doc) { - nrMatchers++; - score += subScorers[root].score(); - countMatches((root<<1)+1); - countMatches((root<<1)+2); - } - } - + /** Returns the score of the current document matching the query. * Initially invalid, until {@link #nextDoc()} is called the first time. */