Index: lucene/contrib/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java =================================================================== --- lucene/contrib/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java (revision 1098643) +++ lucene/contrib/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java (working copy) @@ -231,7 +231,7 @@ if (unsortedTokens != null) { tokensInOriginalOrder = unsortedTokens.toArray(new Token[unsortedTokens .size()]); - ArrayUtil.quickSort(tokensInOriginalOrder, new Comparator() { + ArrayUtil.mergeSort(tokensInOriginalOrder, new Comparator() { public int compare(Token t1, Token t2) { if (t1.startOffset() == t2.startOffset()) return t1.endOffset() - t2.endOffset(); Index: lucene/src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/IndexReader.java (revision 1098643) +++ lucene/src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -1420,7 +1420,7 @@ cfr = new CompoundFileReader(dir, filename); String [] files = cfr.listAll(); - ArrayUtil.quickSort(files); // sort the array of filename so that the output is more readable + ArrayUtil.mergeSort(files); // sort the array of filename so that the output is more readable for (int i = 0; i < files.length; ++i) { long len = cfr.fileLength(files[i]); Index: lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java =================================================================== --- lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java (revision 1098643) +++ lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java (working copy) @@ -219,7 +219,7 @@ // sort by increasing docFreq order if (slop == 0) { - ArrayUtil.quickSort(postingsFreqs); + ArrayUtil.mergeSort(postingsFreqs); } if (slop == 0) { Index: lucene/src/java/org/apache/lucene/search/PhraseQuery.java =================================================================== --- lucene/src/java/org/apache/lucene/search/PhraseQuery.java (revision 1098643) +++ lucene/src/java/org/apache/lucene/search/PhraseQuery.java (working copy) @@ -234,7 +234,7 @@ // sort by increasing docFreq order if (slop == 0) { - ArrayUtil.quickSort(postingsFreqs); + ArrayUtil.mergeSort(postingsFreqs); } if (slop == 0) { // optimize exact case Index: lucene/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java =================================================================== --- lucene/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java (revision 1098643) +++ lucene/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java (working copy) @@ -190,7 +190,7 @@ /** Advance the subSpans to the same document */ private boolean toSameDoc() throws IOException { - ArrayUtil.quickSort(subSpansByDoc, spanDocComparator); + ArrayUtil.mergeSort(subSpansByDoc, spanDocComparator); int firstIndex = 0; int maxDoc = subSpansByDoc[subSpansByDoc.length - 1].doc(); while (subSpansByDoc[firstIndex].doc() != maxDoc) { Index: lucene/src/java/org/apache/lucene/search/TopTermsRewrite.java =================================================================== --- lucene/src/java/org/apache/lucene/search/TopTermsRewrite.java (revision 1098643) +++ lucene/src/java/org/apache/lucene/search/TopTermsRewrite.java (working copy) @@ -134,7 +134,7 @@ final Term placeholderTerm = new Term(query.field); final Q q = getTopLevelQuery(); final ScoreTerm[] scoreTerms = stQueue.toArray(new ScoreTerm[stQueue.size()]); - ArrayUtil.quickSort(scoreTerms, scoreTermSortByTermComp); + ArrayUtil.mergeSort(scoreTerms, scoreTermSortByTermComp); for (final ScoreTerm st : scoreTerms) { final Term term = placeholderTerm.createTerm(st.bytes); assert reader.docFreq(term) == st.termState.docFreq() : "reader DF is " + reader.docFreq(term) + " vs " + st.termState.docFreq(); Index: lucene/src/java/org/apache/lucene/util/SorterTemplate.java =================================================================== --- lucene/src/java/org/apache/lucene/util/SorterTemplate.java (revision 1098643) +++ lucene/src/java/org/apache/lucene/util/SorterTemplate.java (working copy) @@ -30,7 +30,6 @@ public abstract class SorterTemplate { private static final int MERGESORT_THRESHOLD = 12; - private static final int MERGE_TO_QUICKSORT_THRESHOLD = 40; private static final int QUICKSORT_THRESHOLD = 7; /** Implement this method, that swaps slots {@code i} and {@code j} in your data */ @@ -63,17 +62,26 @@ /** Sorts via in-place, but unstable, QuickSort algorithm. * For small collections falls back to {@link #insertionSort(int,int)}. */ - public final void quickSort(int lo, int hi) { - quickSort(lo, hi, MERGE_TO_QUICKSORT_THRESHOLD); + public final void quickSort(final int lo, final int hi) { + if (hi <= lo) return; + // from Integer's Javadocs: ceil(log2(x)) = 32 - numberOfLeadingZeros(x - 1) + quickSort(lo, hi, (32 - Integer.numberOfLeadingZeros(hi - lo)) << 1); } private void quickSort(int lo, int hi, int maxDepth) { + // fall back to insertion when array has short length final int diff = hi - lo; if (diff <= QUICKSORT_THRESHOLD) { insertionSort(lo, hi); return; } + // fall back to merge sort when recursion depth gets too big + if (--maxDepth == 0) { + mergeSort(lo, hi); + return; + } + final int mid = lo + (diff >>> 1); if (compare(lo, mid) > 0) { @@ -106,16 +114,8 @@ } } - // fall back to merge sort when recursion depth gets too big - if (maxDepth == 0) { - // for testing: new Exception("Hit recursion depth limit").printStackTrace(); - mergeSort(lo, left); - mergeSort(left + 1, hi); - } else { - --maxDepth; - quickSort(lo, left, maxDepth); - quickSort(left + 1, hi, maxDepth); - } + quickSort(lo, left, maxDepth); + quickSort(left + 1, hi, maxDepth); } /** Sorts via stable in-place MergeSort algorithm