8236641: Improve Set.of(...).iterator() warmup characteristics

Reviewed-by: smarks, jrose, fweimer
This commit is contained in:
Claes Redestad 2020-01-21 22:21:15 +01:00
parent d2cd7a5096
commit a19ff9d98a

View File

@ -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