是否有任何性能差异之间的循环上的一个原始阵?

假设:

double[] doubleArray = new double[300000];


for (double var: doubleArray) 
   someComplexCalculation(var);

或者:

for ( int i = 0, y = doubleArray.length; i < y; i++)
   someComplexCalculation(doubleArray[i]);

测试结果

我实际上分析:

Total timeused for modern loop= 13269ms
Total timeused for old loop   = 15370ms

所以现代化的循环的实际运行得更快,至少在我的Mac OS x JVM1.5.

有帮助吗?

解决方案

你的手写的,"老"形式执行减少指令,并且可以更快,尽管你已经到简在一定准时编译器肯定知道。"新"形式绝对是 速度更快。

如果你看到的拆卸码(汇编的太阳JAVA1.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: }

所以,你可以看到更多的地方变量使用。分配 doubleArraytmp 在1号线"额外",但是它不会发生的循环,并且可能无法被测量。分配到 var 在第3行也是额外的。如果是有区别性能,这会是负责。

1号线似乎是不必要的,但它的样板,以缓的结果,如果该阵列计算方法前进入的循环。

这就是说,我会使用新的形式,除非你需要做的事情与指数变量。任一性能差异可能是优化通过JIT编译器在运行时,新形式更清楚的。如果你继续这样做"手",可能会错过了关于未来优化。一般来说,一个很好的编译器可以优化"愚蠢的"代码,但绊在"聪明"的代码。

其他提示

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

有时候人们会学习“模式”。这似乎优化了一些操作,但在下一版本的Java中,这些模式实际上更慢。

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

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

及时编译意味着它偶尔可以胜过C,并且在某些情况下它没有理由不能胜过静态汇编语言(程序集无法事先确定不需要调用,Java有时可以做只是那个。

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

为什么不亲自测量?

这听起来有点刺耳,但这类问题很容易验证自己。

只需创建数组并执行1000次或更多次循环,然后测量时间。重复几次以消除毛刺。

没有区别。 Java会将增强型转换为正常的for循环。增强的仅仅是“语法糖”。两个循环生成的字节码相同。

即使在我之前的回答之后,我对你的问题也很好奇。所以我决定自己检查一下。我写了这段小代码(请忽略关于检查数字是否为素数的数学正确性; - )):

public class TestEnhancedFor {

    public static void main(String args[]){
        new TestEnhancedFor();
    }

    public TestEnhancedFor(){
        int numberOfItems = 100000;
        double[] items = getArrayOfItems(numberOfItems);
        int repetitions = 0;
        long start, end;

        do {
            start = System.currentTimeMillis();
            doNormalFor(items);
            end = System.currentTimeMillis();
            System.out.printf("Normal For. Repetition %d: %d\n", 
                    repetitions, end-start);

            start = System.currentTimeMillis();
            doEnhancedFor(items);
            end = System.currentTimeMillis();
            System.out.printf("Enhanced For. Repetition %d: %d\n\n", 
                    repetitions, end-start);

        } while (++repetitions < 5);
    }

    private double[] getArrayOfItems(int numberOfItems){
        double[] items = new double[numberOfItems];
        for (int i=0; i < numberOfItems; i++)
            items[i] = i;
        return items;
    }

    private void doSomeComplexCalculation(double item){
        // check if item is prime number
        for (int i = 3; i < item / 2; i+=2){
            if ((item / i) == (int) (item / i)) break;
        }
    }

    private void doNormalFor(double[] items){
        for (int i = 0; i < items.length; i++)
            doSomeComplexCalculation(items[i]);
    }

    private void doEnhancedFor(double[] items){
        for (double item : items)
            doSomeComplexCalculation(item);
    }

}

运行应用程序给了我以下结果:

  

正常。重复0:5594   增强功能。重复0:5594

     

正常。重复1:5531   增强功能。重复1:5547

     

正常。重复2:5532   增强功能。重复2:5578

     

正常。重复3:5531   增强功能。重复3:5531

     

正常。重复4:5547   增强功能。重复4:5532

正如我们所看到的,结果之间的差异非常小,有时正常循环运行得更快,有时增强循环更快。由于我的电脑中还有其他应用程序打开,我觉得很正常。此外,只有第一次执行比其他执行慢 - 我相信这与JIT优化有关。

正常循环的平均时间(不包括第一次重复)为5535,25ms,增强循环的平均时间为5547ms。但是我们可以看到两个循环的最佳运行时间是相同的(5531ms),所以我认为我们可以得出两个循环具有相同性能的结论 - 并且经过的时间变化是由于其他应用程序(甚至机器的操作系统。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top