java为什么LongStream reduce和sum性能之间存在差异?
我使用LongStream
的rangeClosed
来测试数字总和的性能。当我通过JMH测试性能时,结果如下
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G"})
@State(Scope.Benchmark)
@Warmup(iterations = 10, time = 10)
@Measurement(iterations = 10, time = 10)
public class ParallelStreamBenchmark {
private static final long N = 10000000L;
@Benchmark
public long sequentialSum() {
return Stream.iterate(1L, i -> i + 1).limit(N).reduce(0L, Long::sum);
}
@Benchmark
public long parallelSum() {
return Stream.iterate(1L, i -> i + 1).limit(N).parallel().reduce(0L, Long::sum);
}
@Benchmark
public long rangedReduceSum() {
return LongStream.rangeClosed(1, N).reduce(0, Long::sum);
}
@Benchmark
public long rangedSum() {
return LongStream.rangeClosed(1, N).sum();
}
@Benchmark
public long parallelRangedReduceSum() {
return LongStream.rangeClosed(1, N).parallel().reduce(0L, Long::sum);
}
@Benchmark
public long parallelRangedSum() {
return LongStream.rangeClosed(1, N).parallel().sum();
}
@TearDown(Level.Invocation)
public void tearDown() {
System.gc();
}
Benchmark Mode Cnt Score Error Units
ParallelStreamBenchmark.parallelRangedReduceSum avgt 10 7.895 ± 0.450 ms/op
ParallelStreamBenchmark.parallelRangedSum avgt 10 1.124 ± 0.165 ms/op
ParallelStreamBenchmark.rangedReduceSum avgt 10 6.832 ± 0.165 ms/op
ParallelStreamBenchmark.rangedSum avgt 10 21.564 ± 0.831 ms/op
rangedReduceSum
和rangedSum
之间的区别在于只使用内部函数sum()。为什么会有这么大的性能差异
在验证了sum()
函数最终使用了reduce(0, Long::sum)
之后,它是否与在rangedReduceSum
方法中使用reduce(0, Long::sum)
相同
# 1 楼答案
我做了与OP相同的任务,我可以重现完全相同的结果:第二个任务的速度慢了约3倍。但当我将预热改为仅1次迭代时,事情开始变得有趣:
每项任务在第5次迭代后都会显著减速。对于第二个任务,在第五次迭代之后,它会减慢3倍。如果我们将热身计算为迭代,在10次迭代之后,开始时就要慢下来。看起来像是基准库中的一个bug,它不能很好地与GC配合使用。但正如警告所说,这种情况下的基准测试结果仅供参考