Jea*_*ung 5 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);
}
Run Code Online (Sandbox Code Playgroud)
普通代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Total: 536870895616000
sumWithParallelStream(): 30502 ms
Total: 536870895616000
sequenceSum(): 271 ms
Run Code Online (Sandbox Code Playgroud)
然后我尝试删除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);
}
Run Code Online (Sandbox Code Playgroud)
看到sequenceSum()方法是相同的
新输出:
Total: 536870895616000
sumWithParallelStream(): 13487 ms
Total: 536870895616000
sequenceSum(): 879 ms
Run Code Online (Sandbox Code Playgroud)
我做了这些更改,parallelStream多次添加和删除方法,结果sequenceSum()永不改变,总是200在使用parallelStream其他方法时,以及800何时不使用.在Windows和Ubuntu中进行测试.
最后,还有两个问题,为什么parallelStream第一种方法的使用会影响第二种方法?为什么在数组上存储BigDecimals使第一个方法太慢(800 msto 13000 ms)?
正如 @apangin 的评论所指出的,问题出在垃圾收集器上。
我添加了-XX:+PrintGCDetails命令行参数,可以打印每次 GC 运行的执行时间。然后我可以确认,使用parallelStreamGC 时需要更多时间来运行,可能是因为 Streams API 初始化和预热消耗了更多内存并留下了一些垃圾需要收集。