Java8流出奇怪的行为

时间:2015-06-24 11:43:23

标签: java performance java-8 java-stream

我正在测试一些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 ms13000 ms)?

2 个答案:

答案 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的初始化分配了更多的内存。