-
Bug
-
Resolution: Fixed
-
P3
-
17.0.6, 20, 21
-
b09
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8313414 | 17.0.10-oracle | Weibing Xiao | P3 | Resolved | Fixed | b01 |
JDK-8309086 | 17.0.8 | Aleksey Shipilev | P3 | Resolved | Fixed | b05 |
A DESCRIPTION OF THE PROBLEM :
In previous versions of Java, ThreadLocalRandom.current().doubles().parallel() was approximately the same speed as new SplittableRandom().doubles().parallel(). However, since Java 17, there is heavy contention on the stream when run in parallel.
REGRESSION : Last worked in version 16
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
ThreadLocalRandom.current().doubles(100_000_000).parallel().sum() on Java 16 vs Java 17.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected to complete in about 150 milliseconds.
ACTUAL -
Takes several seconds, depending on the hardware. On 1-8-2 MacBookPro Intel it took 24 seconds. On my 1-6-2 Ubuntu Intel Server it took 4.4 seconds.
---------- BEGIN SOURCE ----------
import java.util.SplittableRandom;
import java.util.concurrent.ThreadLocalRandom;
public class Regression {
public static void main(String... args) throws InterruptedException {
int STREAM_SIZE = 32_000_000;
long srIntsTime = System.nanoTime();
try {
System.out.println("sum ints = " +
new SplittableRandom().ints(STREAM_SIZE)
.parallel()
.sum());
} finally {
srIntsTime = System.nanoTime() - srIntsTime;
System.out.printf("srIntsTime = %dms%n", (srIntsTime / 1_000_000));
}
long tlrIntsTime = System.nanoTime();
try {
System.out.println("sum ints = " +
ThreadLocalRandom.current().ints(STREAM_SIZE)
.parallel()
.sum());
} finally {
tlrIntsTime = System.nanoTime() - tlrIntsTime;
System.out.printf("tlrIntsTime = %dms%n", (tlrIntsTime / 1_000_000));
}
long srLongsTime = System.nanoTime();
try {
System.out.println("sum ints = " +
new SplittableRandom().longs(STREAM_SIZE)
.parallel()
.sum());
} finally {
srLongsTime = System.nanoTime() - srLongsTime;
System.out.printf("srLongsTime = %dms%n", (srLongsTime / 1_000_000));
}
long tlrLongsTime = System.nanoTime();
try {
System.out.println("sum longs = " +
ThreadLocalRandom.current().longs(STREAM_SIZE)
.parallel()
.sum());
} finally {
tlrLongsTime = System.nanoTime() - tlrLongsTime;
System.out.printf("tlrLongsTime = %dms%n", (tlrLongsTime / 1_000_000));
}
long srDoublesTime = System.nanoTime();
try {
System.out.println("sum doubles = " +
new SplittableRandom().doubles(STREAM_SIZE)
.parallel()
.sum());
} finally {
srDoublesTime = System.nanoTime() - srDoublesTime;
System.out.printf("srDoublesTime = %dms%n", (srDoublesTime / 1_000_000));
}
long tlrDoublesTime = System.nanoTime();
try {
System.out.println("sum doubles = " +
ThreadLocalRandom.current().doubles(STREAM_SIZE)
.parallel()
.sum());
} finally {
tlrDoublesTime = System.nanoTime() - tlrDoublesTime;
System.out.printf("tlrDoublesTime = %dms%n", (tlrDoublesTime / 1_000_000));
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use SplittableRandom.
And I have submitted a PR here: https://github.com/openjdk/jdk/pull/12366
(Not in correct format though)
FREQUENCY : always
In previous versions of Java, ThreadLocalRandom.current().doubles().parallel() was approximately the same speed as new SplittableRandom().doubles().parallel(). However, since Java 17, there is heavy contention on the stream when run in parallel.
REGRESSION : Last worked in version 16
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
ThreadLocalRandom.current().doubles(100_000_000).parallel().sum() on Java 16 vs Java 17.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected to complete in about 150 milliseconds.
ACTUAL -
Takes several seconds, depending on the hardware. On 1-8-2 MacBookPro Intel it took 24 seconds. On my 1-6-2 Ubuntu Intel Server it took 4.4 seconds.
---------- BEGIN SOURCE ----------
import java.util.SplittableRandom;
import java.util.concurrent.ThreadLocalRandom;
public class Regression {
public static void main(String... args) throws InterruptedException {
int STREAM_SIZE = 32_000_000;
long srIntsTime = System.nanoTime();
try {
System.out.println("sum ints = " +
new SplittableRandom().ints(STREAM_SIZE)
.parallel()
.sum());
} finally {
srIntsTime = System.nanoTime() - srIntsTime;
System.out.printf("srIntsTime = %dms%n", (srIntsTime / 1_000_000));
}
long tlrIntsTime = System.nanoTime();
try {
System.out.println("sum ints = " +
ThreadLocalRandom.current().ints(STREAM_SIZE)
.parallel()
.sum());
} finally {
tlrIntsTime = System.nanoTime() - tlrIntsTime;
System.out.printf("tlrIntsTime = %dms%n", (tlrIntsTime / 1_000_000));
}
long srLongsTime = System.nanoTime();
try {
System.out.println("sum ints = " +
new SplittableRandom().longs(STREAM_SIZE)
.parallel()
.sum());
} finally {
srLongsTime = System.nanoTime() - srLongsTime;
System.out.printf("srLongsTime = %dms%n", (srLongsTime / 1_000_000));
}
long tlrLongsTime = System.nanoTime();
try {
System.out.println("sum longs = " +
ThreadLocalRandom.current().longs(STREAM_SIZE)
.parallel()
.sum());
} finally {
tlrLongsTime = System.nanoTime() - tlrLongsTime;
System.out.printf("tlrLongsTime = %dms%n", (tlrLongsTime / 1_000_000));
}
long srDoublesTime = System.nanoTime();
try {
System.out.println("sum doubles = " +
new SplittableRandom().doubles(STREAM_SIZE)
.parallel()
.sum());
} finally {
srDoublesTime = System.nanoTime() - srDoublesTime;
System.out.printf("srDoublesTime = %dms%n", (srDoublesTime / 1_000_000));
}
long tlrDoublesTime = System.nanoTime();
try {
System.out.println("sum doubles = " +
ThreadLocalRandom.current().doubles(STREAM_SIZE)
.parallel()
.sum());
} finally {
tlrDoublesTime = System.nanoTime() - tlrDoublesTime;
System.out.printf("tlrDoublesTime = %dms%n", (tlrDoublesTime / 1_000_000));
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use SplittableRandom.
And I have submitted a PR here: https://github.com/openjdk/jdk/pull/12366
(Not in correct format though)
FREQUENCY : always
- backported by
-
JDK-8309086 ThreadLocalRandom.current().doubles().parallel() contention
- Resolved
-
JDK-8313414 ThreadLocalRandom.current().doubles().parallel() contention
- Resolved
- relates to
-
JDK-8193209 JEP 356: Enhanced Pseudo-Random Number Generators
- Closed
- links to
-
Commit openjdk/jdk17u-dev/ff0ee6dd
-
Commit openjdk/jdk/cf6b9eb8
-
Review openjdk/jdk17u-dev/1404
-
Review openjdk/jdk/12366
(2 links to)