我正在运行一些测试(非常基本,没什么特别的),以便检查Java 8流和lambda的性能。使用1000万POJOS的ArrayList
,我想要做的就是获得BigDecimal
字段的平均值。为了获取多个样本,我运行了五次,令我惊讶的是,这五次运行中的第一次比其他运行速度慢得多。我第一次获得0.38秒的值,而其他四个值获得0.04秒。这快10倍!!!我也使用旧学校for(Pojo p : pojos)
做了同样的测试,结果相似。为什么会发生这种情况,我该如何利用它呢?我使用的代码是:
for (int i = 0; i < 5; i++) {
long init = System.nanoTime();
BigDecimal sum = lista.parallelStream().map(x -> x.getCosto()).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal avg = sum.divide(BigDecimal.valueOf(registros));
long end = System.nanoTime();
System.out.println("End of processing: " + avg + " in "
+ ((end - init) / 1000000000.0) + " seconds.");
}
答案 0 :(得分:4)
首次调用Stream API时,需要经常延迟初始化Stream API,其中包括以下步骤:
java.util.stream
package java.lang.invoke
包中加载lambda生成类(如LambdaMetafactory
)。ForkJoinPool
,创建新线程。所有这些步骤仅执行一次。当您再次使用Stream API时,大部分工作已经完成,因此连续启动的速度要快得多。
在您的特定情况下,您正在密集使用堆,因此堆扩大也可能是导致额外缓慢的原因。如果您的-Xms
默认值太小,那么垃圾收集器会执行几个完整的gc循环,直到它将堆扩大到舒适的大小。您可以使用Xms == Xmx(例如-Xmx1G -Xms1G
)运行测试,这可以提高第一次迭代速度。