ConjunctionScorer performance increase: LUCENE-443

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@465043 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yonik Seeley 2006-10-17 20:50:52 +00:00
parent 70472ad2cd
commit 3c35b82cb0
2 changed files with 53 additions and 38 deletions

View File

@ -163,6 +163,10 @@ Optimizations
7. Lazy loaded fields unnecessarily retained an extra copy of loaded
String data. (Yonik Seeley)
8. LUCENE-443: ConjunctionScorer performance increase. Speed up
any BooleanQuery with more than one mandatory clause.
(Abdul Chaudhry, Paul Elschot via Yonik Seeley)
Test Cases
1. Added TestTermScorer.java (Grant Ingersoll)

View File

@ -1,7 +1,7 @@
package org.apache.lucene.search;
/**
* Copyright 2004 The Apache Software Foundation
* Copyright 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,12 +19,13 @@ package org.apache.lucene.search;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
/** Scorer for conjunctions, sets of queries, all of which are required. */
class ConjunctionScorer extends Scorer {
private LinkedList scorers = new LinkedList();
private Scorer[] scorers = new Scorer[2];
private int length = 0;
private int first = 0;
private int last = -1;
private boolean firstTime = true;
private boolean more = true;
private float coord;
@ -34,27 +35,33 @@ class ConjunctionScorer extends Scorer {
}
final void add(Scorer scorer) {
scorers.addLast(scorer);
if (length >= scorers.length) {
// grow the array
Scorer[] temps = new Scorer[scorers.length * 2];
System.arraycopy(scorers, 0, temps, 0, length);
scorers = temps;
}
last += 1;
length += 1;
scorers[last] = scorer;
}
private Scorer first() { return (Scorer)scorers.getFirst(); }
private Scorer last() { return (Scorer)scorers.getLast(); }
public int doc() { return first().doc(); }
public int doc() { return scorers[first].doc(); }
public boolean next() throws IOException {
if (firstTime) {
init(true);
} else if (more) {
more = last().next(); // trigger further scanning
more = scorers[last].next(); // trigger further scanning
}
return doNext();
}
private boolean doNext() throws IOException {
while (more && first().doc() < last().doc()) { // find doc w/ all clauses
more = first().skipTo(last().doc()); // skip first upto last
scorers.addLast(scorers.removeFirst()); // move first to last
while (more && scorers[first].doc() < scorers[last].doc()) { // find doc w/ all clauses
more = scorers[first].skipTo(scorers[last].doc()); // skip first upto last
last = first; // move first to last
first = (first == length-1) ? 0 : first+1;
}
return more; // found a doc with all clauses
}
@ -64,9 +71,10 @@ class ConjunctionScorer extends Scorer {
init(false);
}
Iterator i = scorers.iterator();
while (more && i.hasNext()) {
more = ((Scorer)i.next()).skipTo(target);
for (int i = 0, pos = first; i < length; i++) {
if (!more) break;
more = scorers[pos].skipTo(target);
pos = (pos == length-1) ? 0 : pos+1;
}
if (more)
@ -76,48 +84,51 @@ class ConjunctionScorer extends Scorer {
}
public float score() throws IOException {
float score = 0.0f; // sum scores
Iterator i = scorers.iterator();
while (i.hasNext())
score += ((Scorer)i.next()).score();
score *= coord;
return score;
float sum = 0.0f;
for (int i = 0; i < length; i++) {
sum += scorers[i].score();
}
return sum * coord;
}
private void init(boolean initScorers) throws IOException {
// compute coord factor
coord = getSimilarity().coord(scorers.size(), scorers.size());
coord = getSimilarity().coord(length, length);
more = scorers.size() > 0;
more = length > 0;
if(initScorers){
// move each scorer to its first entry
Iterator i = scorers.iterator();
while (more && i.hasNext()) {
more = ((Scorer)i.next()).next();
for (int i = 0, pos = first; i < length; i++) {
if (!more) break;
more = scorers[pos].next();
pos = (pos == length-1) ? 0 : pos+1;
}
if (more)
sortScorers(); // initial sort of list
// initial sort of simulated list
if (more)
sortScorers();
}
firstTime = false;
}
private void sortScorers() {
// move scorers to an array
Scorer[] array = (Scorer[])scorers.toArray(new Scorer[scorers.size()]);
scorers.clear(); // empty the list
// squeeze the array down for the sort
if (length != scorers.length) {
Scorer[] temps = new Scorer[length];
System.arraycopy(scorers, 0, temps, 0, length);
scorers = temps;
}
// note that this comparator is not consistent with equals!
Arrays.sort(array, new Comparator() { // sort the array
Arrays.sort(scorers, new Comparator() { // sort the array
public int compare(Object o1, Object o2) {
return ((Scorer)o1).doc() - ((Scorer)o2).doc();
}
});
for (int i = 0; i < array.length; i++) {
scorers.addLast(array[i]); // re-build list, now sorted
}
first = 0;
last = length - 1;
}
public Explanation explain(int doc) {