【发布时间】:2015-01-22 11:12:02
【问题描述】:
我不明白为什么要使用 Stream api 在同一个数组上进行多次迭代 导致这样的表现!
请看下面的代码。
public class WhyIsDifferent {
public static void main(String[] args) {
int[] values = getArray();
Iterate(values, 598, 600); // 70 ms
Iterate(values, 200, 202); // 0 ms
Iterate(values, 700, 702); // 0 ms
Iterate(values, 300, 310); // 1 ms
}
public static void Iterate(int[] values, int from, int to) {
long start = System.currentTimeMillis();
IntStream.of(values).filter(i -> i < to && i > from)
.forEach(i ->
System.out.println(i) // do a something
);
System.out.println("Time:" + (System.currentTimeMillis() - start));
}
public static int[] getArray() {
int[] values = new int[1000];
for (int i = 0; i < 1000; i++) {
values[i] = i;
}
return values;
}
}
肯定 JVM 优化了代码,但我不知道这是怎么发生的??太棒了! 你知道为什么会这样吗?
--
我正在 Ubuntu 14.04//Oracle jdk/intel cpu 上进行测试。
【问题讨论】:
-
这是JIT 的工作,我的朋友。
-
@LuiggiMendoza 说了什么;更重要的是,您达到了“最佳状态”,因为默认情况下,Oracle JVM 至少会在同一代码块执行 1000 次后进行优化。
-
对它的一种解释是 lambda 只不过是一个“调用站点”;在您的情况下,鉴于您的 lambda 的简单性,JVM 肯定会完全内联它。在 YouTube 上搜索“lambda peek under the hood”并观看视频:它非常有启发性。事实上,第一次迭代的大部分成本可能是由于最初的链接!
-
在您的情况下,这非常简单:整个运行时中只有一个现有的
Predicate实现。在更复杂的用例中,内置的自我分析器将检测实际执行的代码路径(并且值得优化)。 -
这与 lambdas 无关。 Iterate 的第一次调用总是比较慢;这就是虚拟机的工作方式(解释一段时间,然后进行一些编译等)您需要更仔细地测量。尝试使用 JMH 之类的东西。
标签: java performance lambda java-8 performance-testing