我正在测试一些Java8流API代码,但我无法弄清楚这个代码发生了什么。
我在考虑ParallelStream以及它是如何工作的,我进行了一些比较。 两个不同的方法进行大迭代,添加32.768.000个BigDecimals,一个使用ParallelStream,另一个使用正常迭代。我参加了一项测试,我知道它无效,但有些事情引起了我的注意。
测试是:
并行流:
private static void sumWithParallelStream() {
BigDecimal[] list = new BigDecimal[32_768_000];
BigDecimal total = BigDecimal.ZERO;
for (int i = 0; i < 32_768_000; i++) {
list[i] = new BigDecimal(i);
}
total = Arrays.asList(list).parallelStream().reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("Total: " + total);
}
普通代码:
private static void sequenceSum() {
BigDecimal total = BigDecimal.ZERO;
for (int i = 0; i < 32_768_000; i++) {
total = total.add(new BigDecimal(i));
}
System.out.println("Total: " + total);
}
输出是:
Total: 536870895616000
sumWithParallelStream(): 30502 ms
Total: 536870895616000
sequenceSum(): 271 ms
然后我尝试删除parallelStream
:
private static void sumWithParallelStream() {
BigDecimal[] list = new BigDecimal[32_768_000];
BigDecimal total = BigDecimal.ZERO;
for (int i = 0; i < 32_768_000; i++) {
list[i] = new BigDecimal(i);
total = total.add(list[i]);
}
System.out.println("Total: " + total);
}
看到sequenceSum()方法是相同的
新输出:
Total: 536870895616000
sumWithParallelStream(): 13487 ms
Total: 536870895616000
sequenceSum(): 879 ms
我已经做了这些更改,多次添加和删除parallelStream
方法,sequenceSum()
的结果永远不会改变,在200
上使用parallelStream
时总是如此其他方法,以及不使用时800
的内容。在Windows和Ubuntu中进行测试。
最后,我还有两个问题,为什么在第一种方法上使用parallelStream
会对第二种方法产生影响?为什么在数组上存储BigDecimals使得第一种方法过于缓慢(800 ms
到13000 ms
)?
答案 0 :(得分:3)
在第一个示例中,您将分配一个32,768,000个元素的数组,然后通过它进行流式传输。不需要那个数组分配和内存提取,这可能会减慢方法的速度。
IntStream.range(0, limit).parallel()
.mapToObj(BigDecimal::new)
.reduce(BigDecimal.ZERO, BigDecimal::add);
答案 1 :(得分:0)
正如@apangin的评论所指出的,问题出在GC上。
我使用-XX:+ PrintGCDetails参数来打印GC的执行时间,并且使用parallelStream
它们是最差的,可能是因为Streams API的初始化分配了更多的内存。