作为我对使用复杂过滤器或在流中使用多个过滤器之间差异的研究的一部分,我注意到Java 12上的性能比Java 8慢得多。
这些奇怪结果有任何解释吗?我错过了什么吗?
配置:
java 8
- OpenJDK Runtime Environment(版本1.8.0_181-8u181-b13-2〜deb9u1-b13)
- OpenJDK 64位Server VM(构建25.181-b13,混合模式)
java 12
- OpenJDK Runtime Environment(版本12+33)
- OpenJDK 64位Server VM(构建12+33,混合模式,共享)
VM选项:
-XX:+UseG1GC
-server
-Xmx1024m
-Xms1024m
- CPU:8核
JMH吞吐量结果:
- Warmup: 每次10次迭代,持续1秒
- Measurement: 每次10次迭代,持续1秒
- Threads: 1个线程,将同步迭代
- Units: 操作/秒
代码
流+复杂过滤器
public void complexFilter(ExecutionPlan plan, Blackhole blackhole) {
long count = plan.getDoubles()
.stream()
.filter(d -> d < Math.PI
&& d > Math.E
&& d != 3
&& d != 2)
.count();
blackhole.consume(count);
}
流 + 多个筛选器
public void multipleFilters(ExecutionPlan plan, Blackhole blackhole) {
long count = plan.getDoubles()
.stream()
.filter(d -> d > Math.PI)
.filter(d -> d < Math.E)
.filter(d -> d != 3)
.filter(d -> d != 2)
.count();
blackhole.consume(count);
}
并行流 + 复杂筛选器
public void complexFilterParallel(ExecutionPlan plan, Blackhole blackhole) {
long count = plan.getDoubles()
.stream()
.parallel()
.filter(d -> d < Math.PI
&& d > Math.E
&& d != 3
&& d != 2)
.count();
blackhole.consume(count);
}
并行流 + 多个过滤器
public void multipleFiltersParallel(ExecutionPlan plan, Blackhole blackhole) {
long count = plan.getDoubles()
.stream()
.parallel()
.filter(d -> d > Math.PI)
.filter(d -> d < Math.E)
.filter(d -> d != 3)
.filter(d -> d != 2)
.count();
blackhole.consume(count);
}
传统的Java迭代方式
public void oldFashionFilters(ExecutionPlan plan, Blackhole blackhole) {
long count = 0;
for (int i = 0; i < plan.getDoubles().size(); i++) {
if (plan.getDoubles().get(i) > Math.PI
&& plan.getDoubles().get(i) > Math.E
&& plan.getDoubles().get(i) != 3
&& plan.getDoubles().get(i) != 2) {
count = count + 1;
}
}
blackhole.consume(count);
}
您可以通过运行docker命令自行尝试:
对于Java 8:
docker run -it volkodav/java-filter-benchmark:java8
对于Java 12:
docker run -it volkodav/java-filter-benchmark:java12
源代码:
-gc true
很可能会影响到 JDK12 的运行。在每次迭代之前强制进行 Full GC 可能会扰乱垃圾回收的启发式算法。你为什么要开启这个选项呢?请注意不改变原意且使句子更通俗易懂。 - Aleksey Shipilev@Setup(Level.Invocation)
?好像你的负载想要一次性收集所有陷阱 :) - Aleksey Shipilev