为什么一个 40 亿次迭代的 Java 循环只需要 2 毫秒?

2022-08-31 09:18:47

我正在使用2.7 GHz Intel Core i7的笔记本电脑上运行以下Java代码。我打算让它测量完成一个循环需要多长时间,迭代次数为2^32次,我预计大约是1.48秒(4/2.7 = 1.48)。

但实际上它只需要2毫秒,而不是1.48秒。我想知道这是否是下面任何JVM优化的结果?

public static void main(String[] args)
{
    long start = System.nanoTime();

    for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++){
    }
    long finish = System.nanoTime();
    long d = (finish - start) / 1000000;

    System.out.println("Used " + d);
}

答案 1

这里有两种可能性之一:

  1. 编译器意识到循环是多余的,并且什么都不做,所以它优化了它。

  2. JIT(实时编译器)意识到循环是冗余的并且不执行任何操作,因此它对其进行了优化。

现代编译器非常智能;他们可以看到代码何时无用。尝试将一个空循环放入GodBolt并查看输出,然后打开优化,您将看到输出是沿着以下路线的东西-O2

main():
    xor eax, eax
    ret

我想澄清一些事情,在Java中,大多数优化都是由JIT完成的。在其他一些语言(如C / C++)中,大多数优化都是由第一个编译器完成的。


答案 2

它看起来像是由JIT编译器优化的。当我关闭它()时,代码运行速度要慢得多:-Djava.compiler=NONE

$ javac MyClass.java
$ java MyClass
Used 4
$ java -Djava.compiler=NONE MyClass
Used 40409

我把OP的代码放在里面。class MyClass