提交 e8cb5ad9 编写于 作者: D dl

8014076: Arrays parallel and serial sorting improvements

Reviewed-by: chegar, mduigou
上级 a441ff54
...@@ -86,9 +86,13 @@ class ComparableTimSort { ...@@ -86,9 +86,13 @@ class ComparableTimSort {
private static final int INITIAL_TMP_STORAGE_LENGTH = 256; private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
/** /**
* Temp storage for merges. * Temp storage for merges. A workspace array may optionally be
* provided in constructor, and if so will be used as long as it
* is big enough.
*/ */
private Object[] tmp; private Object[] tmp;
private int tmpBase; // base of tmp array slice
private int tmpLen; // length of tmp array slice
/** /**
* A stack of pending runs yet to be merged. Run i starts at * A stack of pending runs yet to be merged. Run i starts at
...@@ -108,15 +112,27 @@ class ComparableTimSort { ...@@ -108,15 +112,27 @@ class ComparableTimSort {
* Creates a TimSort instance to maintain the state of an ongoing sort. * Creates a TimSort instance to maintain the state of an ongoing sort.
* *
* @param a the array to be sorted * @param a the array to be sorted
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
*/ */
private ComparableTimSort(Object[] a) { private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
this.a = a; this.a = a;
// Allocate temp storage (which may be increased later if necessary) // Allocate temp storage (which may be increased later if necessary)
int len = a.length; int len = a.length;
Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ? int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH]; len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
tmp = newArray; if (work == null || workLen < tlen || workBase + tlen > work.length) {
tmp = new Object[tlen];
tmpBase = 0;
tmpLen = tlen;
}
else {
tmp = work;
tmpBase = workBase;
tmpLen = workLen;
}
/* /*
* Allocate runs-to-be-merged stack (which cannot be expanded). The * Allocate runs-to-be-merged stack (which cannot be expanded). The
...@@ -136,17 +152,28 @@ class ComparableTimSort { ...@@ -136,17 +152,28 @@ class ComparableTimSort {
} }
/* /*
* The next two methods (which are package private and static) constitute * The next method (package private and static) constitutes the
* the entire API of this class. Each of these methods obeys the contract * entire API of this class.
* of the public method with the same signature in java.util.Arrays.
*/ */
static void sort(Object[] a) { /**
sort(a, 0, a.length); * Sorts the given range, using the given workspace array slice
} * for temp storage when possible. This method is designed to be
* invoked from public methods (in class Arrays) after performing
* any necessary array bounds checks and expanding parameters into
* the required forms.
*
* @param a the array to be sorted
* @param lo the index of the first element, inclusive, to be sorted
* @param hi the index of the last element, exclusive, to be sorted
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
* @since 1.8
*/
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
static void sort(Object[] a, int lo, int hi) {
rangeCheck(a.length, lo, hi);
int nRemaining = hi - lo; int nRemaining = hi - lo;
if (nRemaining < 2) if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted return; // Arrays of size 0 and 1 are always sorted
...@@ -163,7 +190,7 @@ class ComparableTimSort { ...@@ -163,7 +190,7 @@ class ComparableTimSort {
* extending short natural runs to minRun elements, and merging runs * extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant. * to maintain stack invariant.
*/ */
ComparableTimSort ts = new ComparableTimSort(a); ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
int minRun = minRunLength(nRemaining); int minRun = minRunLength(nRemaining);
do { do {
// Identify next run // Identify next run
...@@ -619,11 +646,11 @@ class ComparableTimSort { ...@@ -619,11 +646,11 @@ class ComparableTimSort {
// Copy first run into temp array // Copy first run into temp array
Object[] a = this.a; // For performance Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len1); Object[] tmp = ensureCapacity(len1);
System.arraycopy(a, base1, tmp, 0, len1);
int cursor1 = 0; // Indexes into tmp array int cursor1 = tmpBase; // Indexes into tmp array
int cursor2 = base2; // Indexes int a int cursor2 = base2; // Indexes int a
int dest = base1; // Indexes int a int dest = base1; // Indexes int a
System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases // Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++]; a[dest++] = a[cursor2++];
...@@ -736,16 +763,17 @@ class ComparableTimSort { ...@@ -736,16 +763,17 @@ class ComparableTimSort {
// Copy second run into temp array // Copy second run into temp array
Object[] a = this.a; // For performance Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len2); Object[] tmp = ensureCapacity(len2);
System.arraycopy(a, base2, tmp, 0, len2); int tmpBase = this.tmpBase;
System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a int cursor1 = base1 + len1 - 1; // Indexes into a
int cursor2 = len2 - 1; // Indexes into tmp array int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
int dest = base2 + len2 - 1; // Indexes into a int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases // Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--]; a[dest--] = a[cursor1--];
if (--len1 == 0) { if (--len1 == 0) {
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
return; return;
} }
if (len2 == 1) { if (len2 == 1) {
...@@ -803,7 +831,7 @@ class ComparableTimSort { ...@@ -803,7 +831,7 @@ class ComparableTimSort {
if (--len2 == 1) if (--len2 == 1)
break outer; break outer;
count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1); count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
if (count2 != 0) { if (count2 != 0) {
dest -= count2; dest -= count2;
cursor2 -= count2; cursor2 -= count2;
...@@ -835,7 +863,7 @@ class ComparableTimSort { ...@@ -835,7 +863,7 @@ class ComparableTimSort {
} else { } else {
assert len1 == 0; assert len1 == 0;
assert len2 > 0; assert len2 > 0;
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
} }
} }
...@@ -848,7 +876,7 @@ class ComparableTimSort { ...@@ -848,7 +876,7 @@ class ComparableTimSort {
* @return tmp, whether or not it grew * @return tmp, whether or not it grew
*/ */
private Object[] ensureCapacity(int minCapacity) { private Object[] ensureCapacity(int minCapacity) {
if (tmp.length < minCapacity) { if (tmpLen < minCapacity) {
// Compute smallest power of 2 > minCapacity // Compute smallest power of 2 > minCapacity
int newSize = minCapacity; int newSize = minCapacity;
newSize |= newSize >> 1; newSize |= newSize >> 1;
...@@ -863,30 +891,13 @@ class ComparableTimSort { ...@@ -863,30 +891,13 @@ class ComparableTimSort {
else else
newSize = Math.min(newSize, a.length >>> 1); newSize = Math.min(newSize, a.length >>> 1);
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
Object[] newArray = new Object[newSize]; Object[] newArray = new Object[newSize];
tmp = newArray; tmp = newArray;
tmpLen = newSize;
tmpBase = 0;
} }
return tmp; return tmp;
} }
/**
* Checks that fromIndex and toIndex are in range, and throws an
* appropriate exception if they aren't.
*
* @param arrayLen the length of the array
* @param fromIndex the index of the first element of the range
* @param toIndex the index after the last element of the range
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0
* or toIndex > arrayLen
*/
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex+")");
if (fromIndex < 0)
throw new ArrayIndexOutOfBoundsException(fromIndex);
if (toIndex > arrayLen)
throw new ArrayIndexOutOfBoundsException(toIndex);
}
} }
...@@ -50,11 +50,11 @@ public class ParallelSorting { ...@@ -50,11 +50,11 @@ public class ParallelSorting {
// Array lengths used in a long run (default) // Array lengths used in a long run (default)
private static final int[] LONG_RUN_LENGTHS = { private static final int[] LONG_RUN_LENGTHS = {
1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 }; 1000, 10000, 100000, 1000000 };
// Array lengths used in a short run // Array lengths used in a short run
private static final int[] SHORT_RUN_LENGTHS = { private static final int[] SHORT_RUN_LENGTHS = {
1, 2, 3, 21, 55, 1000, 10000 }; 5000, 9000, 10000, 12000 };
// Random initial values used in a long run (default) // Random initial values used in a long run (default)
private static final long[] LONG_RUN_RANDOMS = { 666, 0xC0FFEE, 999 }; private static final long[] LONG_RUN_RANDOMS = { 666, 0xC0FFEE, 999 };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册