8236641: Improve Set.of(...).iterator() warmup characteristics
Reviewed-by: smarks, jrose, fweimer
This commit is contained in:
parent
d2cd7a5096
commit
a19ff9d98a
@ -55,7 +55,7 @@ class ImmutableCollections {
|
||||
* it needs to vary sufficiently from one run to the next so that iteration order
|
||||
* will vary between JVM runs.
|
||||
*/
|
||||
static final int SALT;
|
||||
private static final long SALT32L;
|
||||
|
||||
/**
|
||||
* For set and map iteration, we will iterate in "reverse" stochastically,
|
||||
@ -63,10 +63,18 @@ class ImmutableCollections {
|
||||
*/
|
||||
private static final boolean REVERSE;
|
||||
static {
|
||||
long color = 0x243F_6A88_85A3_08D3L; // pi slice
|
||||
// to generate a reasonably random and well-mixed SALT, use an arbitrary
|
||||
// value (a slice of pi), multiply with the System.nanoTime, then pick
|
||||
// the mid 32-bits from the product. By picking a SALT value in the
|
||||
// [0 ... 0xFFFF_FFFFL == 2^32-1] range, we ensure that for any positive
|
||||
// int N, (SALT32L * N) >> 32 is a number in the [0 ... N-1] range. This
|
||||
// property will be used to avoid more expensive modulo-based
|
||||
// calculations.
|
||||
long color = 0x243F_6A88_85A3_08D3L; // slice of pi
|
||||
long seed = System.nanoTime();
|
||||
SALT = (int)((color * seed) >> 16); // avoid LSB and MSB
|
||||
REVERSE = SALT >= 0;
|
||||
SALT32L = (int)((color * seed) >> 16) & 0xFFFF_FFFFL;
|
||||
// use the lowest bit to determine if we should reverse iteration
|
||||
REVERSE = (SALT32L & 1) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -639,7 +647,7 @@ class ImmutableCollections {
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<>() {
|
||||
private int idx = size();
|
||||
private int idx = (e1 == EMPTY) ? 1 : 2;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
@ -765,10 +773,10 @@ class ImmutableCollections {
|
||||
private int idx;
|
||||
|
||||
SetNIterator() {
|
||||
remaining = size();
|
||||
if (remaining > 0) {
|
||||
idx = Math.floorMod(SALT, elements.length);
|
||||
}
|
||||
remaining = size;
|
||||
// pick a starting index in the [0 .. element.length-1] range
|
||||
// randomly based on SALT32L
|
||||
idx = (int) ((SALT32L * elements.length) >>> 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -776,26 +784,25 @@ class ImmutableCollections {
|
||||
return remaining > 0;
|
||||
}
|
||||
|
||||
private int nextIndex() {
|
||||
int idx = this.idx;
|
||||
if (REVERSE) {
|
||||
if (++idx >= elements.length) {
|
||||
idx = 0;
|
||||
}
|
||||
} else {
|
||||
if (--idx < 0) {
|
||||
idx = elements.length - 1;
|
||||
}
|
||||
}
|
||||
return this.idx = idx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (remaining > 0) {
|
||||
E element;
|
||||
// skip null elements
|
||||
while ((element = elements[nextIndex()]) == null) {}
|
||||
int idx = this.idx;
|
||||
int len = elements.length;
|
||||
// step to the next element; skip null elements
|
||||
do {
|
||||
if (REVERSE) {
|
||||
if (++idx >= len) {
|
||||
idx = 0;
|
||||
}
|
||||
} else {
|
||||
if (--idx < 0) {
|
||||
idx = len - 1;
|
||||
}
|
||||
}
|
||||
} while ((element = elements[idx]) == null);
|
||||
this.idx = idx;
|
||||
remaining--;
|
||||
return element;
|
||||
} else {
|
||||
@ -1061,10 +1068,10 @@ class ImmutableCollections {
|
||||
private int idx;
|
||||
|
||||
MapNIterator() {
|
||||
remaining = size();
|
||||
if (remaining > 0) {
|
||||
idx = Math.floorMod(SALT, table.length >> 1) << 1;
|
||||
}
|
||||
remaining = size;
|
||||
// pick an even starting index in the [0 .. table.length-1]
|
||||
// range randomly based on SALT32L
|
||||
idx = (int) ((SALT32L * (table.length >> 1)) >>> 32) << 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user