I work on a Jetty web app that was running on Java 16. I tried to upgrade it to Java 17 but there were critical performance issues caused entirely by one call to parallelStream()
.
The only changes are the Java version bump from 16 to 17, --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED
and the runtime bump from openjdk:16.0.1-jdk-oraclelinux8
to openjdk:17.0.1-jdk-oraclelinux8
.
We managed to obtain a thread dump and it contains many of these:
"qtp1368594774-200" #200 prio=5 os_prio=0 cpu=475.94ms elapsed=7189.65s tid=0x00007fd49c50cc10 nid=0xd1 waiting on condition [0x00007fd48fef7000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park(java.base@17.0.1/Native Method)
- parking to wait for <0x00000007b73439a8> (a java.util.stream.ReduceOps$ReduceTask)
at java.util.concurrent.locks.LockSupport.park(java.base@17.0.1/LockSupport.java:341)
at java.util.concurrent.ForkJoinTask.awaitDone(java.base@17.0.1/ForkJoinTask.java:468)
at java.util.concurrent.ForkJoinTask.invoke(java.base@17.0.1/ForkJoinTask.java:687)
at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(java.base@17.0.1/ReduceOps.java:927)
at java.util.stream.AbstractPipeline.evaluate(java.base@17.0.1/AbstractPipeline.java:233)
at java.util.stream.ReferencePipeline.collect(java.base@17.0.1/ReferencePipeline.java:682)
at com.stackoverflowexample.aMethodThatDoesBlockingIOUsingParallelStream()
The code that is causing the issue is something like:
list.parallelStream()
.map(this::callRestServiceToGetSomeData)
.collect(Collectors.toUnmodifiableList());
This image shows thread use before upgrading from jdk16 (LHS), upgrading to jdk17 (the huge spike in the middle), then removing the call to parallelStream()
still on jdk17 (RHS):
What change in Java 17 (openjdk-17.0.1_linux-x64_bin.tar.gz) has caused this?