myArray[index2] += 32;
}
long result = 0;
for(index1 = THRESHOLD - 1; index1 > 1; index1-=100)
result += myArray[index1];
//Stop playing,let's see how long it took
System.out.println(result);
System.out.println((System.currentTimeMillis())-begin+"ms");
}
我们来看看:
private static int [] myArray = new int [THRESHOLD];
在W7 64位下,基于10次连续运行,我得到以下结果:
> THRESHOLD = 10 ^ 7,1.7.0u09客户端VM(Oracle):
>当myArray不是最终版时,运行时间约为2133毫秒.
>当myArray成为最终版时,运行时间约为2287毫秒.
> -server VM产生类似的数字,即2131ms和2284ms.
> THRESHOLD = 3×10 ^ 7,运行在~7647ms.
>当myArray最终时,在~8190ms运行.
> -server VM产生~7653ms和~8150ms.
> THRESHOLD = 3×10 ^ 7,1.7.0u01客户端VM(Oracle):
>当myArray不是最终版时,运行在~8166ms.
>当myArray是最终版时,运行时间约为9694ms.这差异超过15%!
> -server VM产生了可忽略的差异,有利于非最终版本,大约1%.
备注:我使用JDK 1.7.0u09的javac生成的字节码进行所有测试.除了myArray声明之外,两个版本生成的字节码完全相同,这是预期的.
那么为什么带有静态最终myArray的版本比带有静态myArray的版本慢?
编辑(使用Aubin的我的代码片段版本):
似乎版本与final关键字之间的差异与不仅仅在第一次迭代中的差异.不知何故,具有final的版本总是比没有第一次迭代时的版本慢,然后下一次迭代具有相似的时序.
例如,使用THRESHOLD = 10 ^ 8并使用1.7.0u09客户端运行时,第一次计算需要大约35秒,而第二次“仅”需要30秒.
显然,VM执行了一个优化,是JIT在运行,为什么它没有提前启动(例如通过编译嵌套循环的第二级,这部分是热点)?
请注意,我的备注对1.7.0u01客户端VM仍然有效.对于那个版本(也许是早期版本),带有final myArray的代码比没有此关键字的代码运行得慢:2671ms vs 2331ms,基于200次迭代.