【发布时间】:2019-09-28 02:42:47
【问题描述】:
我用最后的示例代码来衡量性能。
如果我调用 checkPerformanceResult 方法并将参数 numberOfTimes 设置为 100,则并行流的性能优于重要的顺序流(sequential=346,parallel=78)。
如果我将参数设置为 1000,则顺序流的性能优于并行流显着(sequential=3239,parallel=9337)。
我跑了很多次,结果都是一样的。
有人可以解释一下这种行为以及这里发生了什么吗?
public class ParallelStreamExample {
public static long checkPerformanceResult(Supplier<Integer> s, int numberOfTimes) {
long startTime = System.currentTimeMillis();
for(int i = 0; i < numberOfTimes; i++) {
s.get();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static int sumSequentialStreamThread() {
IntStream.rangeClosed(1, 10000000).sum();
return 0;
}
public static int sumParallelStreamThread() {
IntStream.rangeClosed(1, 10000000)
.parallel().sum();
return 0;
}
public static void main(String[] args) {
System.out.println(checkPerformanceResult(ParallelStreamExample::sumSequentialStreamThread, 1000));
System.out.println("break");
System.out.println(checkPerformanceResult(ParallelStreamExample::sumParallelStreamThread, 1000));
}
}
【问题讨论】:
-
微基准测试是出了名的不可靠。您运行每个测试一次。此外,您返回一个常数零。正确的算法是
return ((n + 1) * n) / 2;- 不需要循环或范围。 -
在这种情况下返回一个常量应该没有任何影响?此外,我同意,这令人困惑。此外,我对解决求和问题的最快算法不感兴趣。我想看看流的表现。
-
我认为如果有一种方法可以提示流减少操作可以通过分而治之的方法来完成,那么并行会更快。我认为它目前正在做的是产生
N线程,每个线程都有一个数字,然后终端操作仍然必须按顺序评估每个线程的值并组合相邻的线程。基本上,您正在创建大量工作人员,但强制他们全部按顺序通过您的sum操作。换句话说,并行操作应该发生在 reducer (sum),而不是 producer (stream) -
我怀疑这(部分)是由于糟糕的基准设计/实施。使用 jmh (baeldung.com/java-microbenchmark-harness) 或类似方法重新进行基准测试。分析有问题的基准测试的结果没有什么意义。
-
@smac89
IntStream.rangeClosed(1, 10000000) .parallel() .sum();的并行处理没有问题这里没有“生产者-消费者”的事情。
标签: java java-8 parallel-processing java-stream