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上.
我的意见是你不知道也不应该猜.这些天试图超越编译器是徒劳的.
有些人曾经学过"模式"似乎可以优化某些操作,但在下一版本的Java中,这些模式实际上更慢.
始终尽可能清楚地写出来并且不要担心优化,直到你手中有一些用户规范并且无法满足某些要求,甚至在测试之前和之后要非常小心地运行以确保你的"修复"实际上改进了它,足以使该要求通过.
编译器可以做一些令人惊奇的东西,这些东西真的会让你大吃一惊,即使你做了一些迭代超过一个大范围的测试,如果你有一个较小的范围或改变循环内部发生的事情,它可能会完全不同.
及时编译意味着它偶尔可以胜过C,并且在某些情况下它没有理由不能胜过静态汇编语言(汇编不能事先确定不需要调用,Java有时可以做到这一点.
总结一下:你可以在代码中加入的最大价值就是把它写成可读的.
您手写的“旧”形式执行的指令更少,并且可能更快,尽管您必须在给定的 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 编译器在运行时优化掉,并且新的形式更加清晰。如果您继续“手动”执行此操作,您可能会错过未来的优化。一般来说,一个好的编译器可以很好地优化“愚蠢”的代码,但会在“智能”的代码上失败。
| 归档时间: |
|
| 查看次数: |
7206 次 |
| 最近记录: |