【发布时间】:2011-02-06 01:10:56
【问题描述】:
我有以下两个程序:
long startTime = System.currentTimeMillis();
for (int i = 0; i < N; i++);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");
和
long startTime = System.currentTimeMillis();
for (long i = 0; i < N; i++);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");
注意:唯一的区别是循环变量的类型(int 和long)。
当我运行它时,第一个程序始终在 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)
我使用的是 Windows XP Professional x64 Edition Service Pack 2,配备 2.40GHz 的 Intel Core2 Quad CPU。
免责声明
我知道微基准在生产环境中没有用处。我也知道System.currentTimeMillis() 并不像它的名字所暗示的那么准确。这只是我在闲逛时注意到的事情,我只是好奇为什么会发生这种情况;仅此而已。
【问题讨论】:
-
我绝对同意@Andrzej 的观点,但如果只是出于好奇,您可以使用 PrintAssembly 插件来真正查看生成的代码:wikis.sun.com/display/HotSpotInternals/PrintAssembly
-
如果使用 -Xint 标志运行会发生什么?这可以防止 Hotspot 编译,因此您将获得更好的比较。
-
@Steven:但使用
-Xint的结果甚至更少对于任何类似于实际使用的东西都有意义。 -
我很好奇 PrintAssembly 会显示什么,如果有人想运行它并发布结果...
标签: java performance optimization jit