我在Surface Pro 2平板电脑上运行带有Java 7更新45 x64(未安装32位Java)的Windows 8.1 x64。
下面的代码在i的类型为long时需要1688毫秒,在i是int的情况下需要109毫秒。为什么长(64位类型)比具有64位JVM的64位平台上的int慢一个数量级?
我唯一的猜测是,与64位整数相比,CPU要花费更多的时间来添加32位整数,但这似乎不太可能。我怀疑Haswell不会使用脉动加法器。
我正在Eclipse Kepler SR1中运行它,]。>
这些结果是在调试32位模式下进行的。public class Main { private static long i = Integer.MAX_VALUE; public static void main(String[] args) { System.out.println("Starting the loop"); long startTime = System.currentTimeMillis(); while(!decrementAndCheck()){ } long endTime = System.currentTimeMillis(); System.out.println("Finished the loop in " + (endTime - startTime) + "ms"); } private static boolean decrementAndCheck() { return --i < 0; } }
编辑:这是由VS 2013(以下),同一系统编译的等效C ++代码的结果。
long:72265ms int:74656ms
在64位释放模式下:long:875ms
这表明我观察到的结果是JVM优化怪异而不是CPU限制。
#include "stdafx.h" #include "iostream" #include "windows.h" #include "limits.h" long long i = INT_MAX; using namespace std; boolean decrementAndCheck() { return --i < 0; } int _tmain(int argc, _TCHAR* argv[]) { cout << "Starting the loop" << endl; unsigned long startTime = GetTickCount64(); while (!decrementAndCheck()){ } unsigned long endTime = GetTickCount64(); cout << "Finished the loop in " << (endTime - startTime) << "ms" << endl; }
编辑:刚刚在Java 8 RTM中再次尝试了此操作,没有明显变化。
我正在Surface Pro 2平板电脑上运行带有Java 7更新45 x64(未安装32位Java)的Windows 8.1 x64。当i的类型为long时,下面的代码花费1688ms,而当i的类型为int时,下面的代码花费109ms。为什么是...
当您使用long
s时,我的JVM对内部循环执行了这一非常简单的操作:
JVM堆栈是根据words
Java虚拟机中数据的基本单位是单词。选择正确的字长取决于JVM的实现。 JVM实现应选择最小字长为32位。它可以选择较高的字长以提高效率。也没有任何限制,即64位JVM仅应选择64位字。
我刚刚使用caliper编写了一个基准。
为了记录,此版本进行了粗略的“热身”:
用于记录:
我没有要测试的64位计算机,但相差很大,这表明工作的字节码比更长的要多。
我具有相同的差值,int 47ms,长750ms。看来问题仅以递减的方式出现。如果将--i更改为i = i-10,则int和long的基准测试结果相同。