int与long的迭代速度

jqn*_*qno 8 java optimization performance jit

我有以下两个程序:

long startTime = System.currentTimeMillis();
for (int i = 0; i < N; i++);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");
Run Code Online (Sandbox Code Playgroud)

long startTime = System.currentTimeMillis();
for (long i = 0; i < N; i++);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");
Run Code Online (Sandbox Code Playgroud)

注意:唯一的区别是循环变量(intlong)的类型.

当我运行它时,第一个程序始终打印0到16毫秒,无论值是什么N.第二个需要更长的时间.因为N == Integer.MAX_VALUE,它在我的机器上运行大约1800毫秒.运行时间似乎或多或少是线性的N.

那么为什么呢?

我想JIT编译器会优化int循环到死.并且有充分的理由,因为显然它什么都不做.但是为什么它也不是这样做的long呢?

一位同事认为我们可能正在测量JIT编译器在long循环中的工作,但由于运行时似乎是线性的N,所以情况可能并非如此.

我正在使用JDK 1.6.0更新17:

C:\>java -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)
Run Code Online (Sandbox Code Playgroud)

我使用的是Windows XP Professional x64 Edition,Service Pack 2,配备2.40GHz的Intel Core2 Quad CPU.


免责声明

我知道微基准测试在生产中没用.我也知道这System.currentTimeMillis()不像它的名字那么准确.这只是我在鬼混时注意到的事情,我只是好奇为什么会发生这种情况; 而已.

And*_*yle 5

这是一个有趣的问题,但说实话,我不相信考虑Hotspot在这里的行为会产生有用的信息.你得到的任何答案都不会在一般情况下转移(因为我们正在研究Hotspot在某种特定情况下执行的优化),所以它们会帮助你理解为什么一个no-op比另一个更快,但他们不会帮助你写更快的"真实"程序.

在这类事情上编写非常容易误导性的微基准测试也非常容易 - 请参阅这篇IBM DW文章,了解一些常见的陷阱,如何避免它们以及对您正在做的事情的一些一般性评论.

所以这真的是一个"无评论"的答案,但我认为这是唯一有效的答案.编译时平凡无操作循环并不需要要快,所以编译器不优化要快一些的这些条件.