现代for循环的原始数组

Dan*_*Dan 13 java arrays iteration performance

原始数组上的for循环之间是否存在性能差异?

假设:

double[] doubleArray = new double[300000];


for (double var: doubleArray) 
   someComplexCalculation(var);
Run Code Online (Sandbox Code Playgroud)

要么 :

for ( int i = 0, y = doubleArray.length; i < y; i++)
   someComplexCalculation(doubleArray[i]);
Run Code Online (Sandbox Code Playgroud)

测试结果

我实际上描述了它:

Total timeused for modern loop= 13269ms
Total timeused for old loop   = 15370ms
Run Code Online (Sandbox Code Playgroud)

所以现代循环实际上运行得更快,至少在我的Mac OSX JVM 1.5上.

Bil*_*l K 5

我的意见是你不知道也不应该猜.这些天试图超越编译器是徒劳的.

有些人曾经学过"模式"似乎可以优化某些操作,但在下一版本的Java中,这些模式实际上更慢.

始终尽可能清楚地写出来并且不要担心优化,直到你手中有一些用户规范并且无法满足某些要求,甚至在测试之前和之后要非常小心地运行以确保你的"修复"实际上改进了它,足以使该要求通过.

编译器可以做一些令人惊奇的东西,这些东西真的会让你大吃一惊,即使你做了一些迭代超过一个大范围的测试,如果你有一个较小的范围或改变循环内部发生的事情,它可能会完全不同.

及时编译意味着它偶尔可以胜过C,并且在某些情况下它没有理由不能胜过静态汇编语言(汇编不能事先确定不需要调用,Java有时可以做到这一点.

总结一下:你可以在代码中加入的最大价值就是把它写成可读的.


eri*_*son 5

您手写的“旧”形式执行的指令更少,并且可能更快,尽管您必须在给定的 JIT 编译器下对其进行分析才能确定。“新”形式绝对不会更快。

如果您查看反汇编代码(由 Sun 的 JDK 1.5 编译),您会发现“新”形式相当于以下代码:

1: double[] tmp = doubleArray;
2: for (int i = 0, y = tmp.length; i < y; i++) {
3:   double var = tmp[i];
4:   someComplexCalculation(var);
5: }
Run Code Online (Sandbox Code Playgroud)

所以,你可以看到使用了更多的局部变量。doubleArray第 1 行对to的赋值tmp是“额外的”,但它不会出现在循环中,并且可能无法测量。第 3 行的分配var也是额外的。如有性能差异,责任自负。

第 1 行可能看起来没有必要,但如果在进入循环之前通过方法计算数组,则它是缓存结果的样板。

也就是说,我会使用新形式,除非您需要对索引变量执行某些操作。任何性能差异都可能被 JIT 编译器在运行时优化掉,并且新的形式更加清晰。如果您继续“手动”执行此操作,您可能会错过未来的优化。一般来说,一个好的编译器可以很好地优化“愚蠢”的代码,但会在“智能”的代码上失败。