为什么JVM不执行代码?

时间:2014-03-06 11:41:39

标签: java jvm

我正在测试分支预测,代码如下:

//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循环的时间很简单。

请注意,sortedSumrandomSum是在循环中分配的,但从未被访问过。

我们这里不讨论分支预测,而是输出结果。 输出是:

random time: 32
sorted time: 1595942

然后,我在第一个(第一个randomArray循环,第二个sortedArray)之前放置第二个for循环。 输出是:

random time: 1541919
sorted time: 40

似乎JVM没有执行第二个循环。我反编译类文件,反编译器不会删除任何内容。

为什么呢?为什么JVM会执行第一个循环?

P.S。 环境是:

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)

3 个答案:

答案 0 :(得分:2)

当您运行足够的代码时,它会触发整个方法(在后台)

这意味着如果你有一个迭代次数超过10K且没有做任何事情的循环,你实际上计算了检测循环没有做任何事情所需的时间并替换它。

在第二个循环的情况下,在任何一种情况下,该方法都已经被优化掉了。

我建议你有一个外循环来运行这个测试3次,你应该明白我的意思。

它可以放弃循环的原因是;

  • 并且您不使用计算的值,因此可以删除calculateSum
  • 然后不需要数组访问
  • 然后循环本身不需要。

答案 1 :(得分:0)

假设这个:

我们在这里讨论即时编译。编译器在开始执行后只会优化一段时间。我猜他会优化一切。只要JIT编译器没有启动,就会执行第一个循环。

答案 2 :(得分:0)

我认为它与Java无关,而是CPU,内存和缓存:

首先System.nanoTime() app在内存中,执行代码在CPU缓存级别1(以CPU的速度)。当程序开始执行时,CPU将开始向前放置内存块 在1级或2级时,所以顺序读/写速度会增加。

尝试使用比CPU级别3缓存大得多的数组,例如: 10MB和随机索引,即以随机顺序准备索引数组。这将消除CPU兑现效应。