我正在测试分支预测,代码如下:
//first loop
int sortedSum = 0;
long sortedStartTime = System.nanoTime();
for (int i = 0; i < sortedArray.length; i++) {
if (sortedArray[i] < 0) {
sortedSum += sortedArray[i];
}
}
long sortedTime = System.nanoTime() - sortedStartTime;
//second loop
int randomSum = 0;
long randomStartTime = System.nanoTime();
for (int i = 0; i < randomArray.length; i++) {
if (randomArray[i] < 0) {
randomSum += randomArray[i];
}
}
long randomTime = System.nanoTime() - randomStartTime;
System.out.println("random time: " + randomTime);
System.out.println("sorted time: " + sortedTime);
打印每个 for 循环的时间很简单。
请注意,sortedSum
和 randomSum
是在循环中分配的,但从未被访问过。
这里我们不讨论分支预测,而是讨论输出结果。 输出为:
random time: 32
sorted time: 1595942
然后,我将第二个for循环放在第一个循环之前(第一个randomArray循环,第二个sortedArray)。 输出为:
random time: 1541919
sorted time: 40
看来 JVM 没有执行第二个循环。我反编译了类文件,反编译器不会删除任何内容。
为什么?为什么 JVM 会执行第一个循环?附注 环境是:
Ubuntu 12.04 LTS
java version "1.7.0_11"
Java(TM) SE Runtime Environment (build 1.7.0_11-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)
最佳答案
当您运行足够多的代码时,它会触发整个方法进行优化(在后台)
这意味着,如果您有一个迭代超过 10K 次的循环并且它不执行任何操作,那么您实际上是在计算检测循环不执行任何操作并替换它所需的时间。
在第二个循环的情况下,无论哪种情况,该方法都已被优化掉。
我建议你有一个外循环运行这个测试 3 次,你应该明白我的意思。
它可以丢弃循环的原因是;
- 并且您不使用计算出的值,因此可以删除
calculateSum
- 那么就不需要数组访问
- 那么循环本身就不需要了。
关于java - 为什么JVM不执行代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22223476/