【问题标题】:Why seperate method works faster than same code inline为什么单独的方法比在线相同的代码工作得更快
【发布时间】:2014-10-23 00:36:07
【问题描述】:

例如在大数组中搜索最大值。单独方法中带有循环的代码比 main 中的相同内联代码运行得更快。在这里运行 10 次以获得平均消耗时间:

最大生成:999999 最大值为 999999 主要消耗时间:1.8210982999999998 ms 最大值为 999999 耗时方法:0.6809502000000001 ms

有人能解释一下为什么会有这样的差异吗?谢谢。

import java.util.Random;

public class Main {
    private static int[] data = new int[1000000];
    private final static int COUNT = 10;


    public static void main(String[] args) {
        initData(data);
        long consumedTime;
        long startTime = System.nanoTime();
        int max = 0;
        for (int x = 0; x < COUNT; x++) {
            max  = data[0];
            for (int i = 0; i < data.length; i++) {
                if (data[i] > max) {
                    max = data[i];
                }
            }
        }
        consumedTime =(System.nanoTime() - startTime);
        System.out.println("Max is "+max+ "  Time consumed main: " + (double) (consumedTime)/1000000/COUNT + " ms");


        startTime = System.nanoTime();
        for (int x = 0; x < COUNT; x++) {
            max = getMaxOnPart();
        }
        consumedTime=(System.nanoTime() - startTime);
        System.out.println("Max is "+max+" Time consumed method: " + (double) (consumedTime)/1000000/COUNT + " ms");
    }

    private static void initData(int[] data) {
        final Random random = new Random();
        int max = 0;
        for (int i = 0; i < data.length; i++) {
            data[i] = random.nextInt(1000000);
            if (max < data[i]) {
                max = data[i];
            }
        }
        System.out.println("  Max generated: " + max);
    }

    private static int getMaxOnPart() {
        int max = data[0];
        for (int i = 0; i < data.length; i++) {
            if (data[i] > max) {
                max = data[i];
            }
        }
        return max;
    }
}

【问题讨论】:

    标签: java methods coding-style inline-code


    【解决方案1】:

    您没有正确/一致地进行测量。在第一个循环中

    long startTime = System.nanoTime();
    

    在 10 次重复循环之外,因此

    consumedTime+=(System.nanoTime() - startTime);
    

    测量 1x + 2x + 3x + ... 会将结果夸大 55 倍(如果我的数学正确的话)。

    而第二个调用函数测量会重置重复 x 10 循环内的 startTime

     startTime = System.nanoTime();
     max = getMaxOnPart();
     consumedTime+=(System.nanoTime() - startTime);
    

    这将总结方法中所用的时间。

    【讨论】:

    • 其实我已经解决了他的问题,而且方法还是比较快的,我会发布一个答案,这样你就可以看到新的代码了。
    • 由于第一个循环的开始时间测量错误而更改了原始帖子。第二个看起来还不错。它增加了 10 倍的时间消耗,就像第一次一样。
    【解决方案2】:

    您的代码中似乎有一些错误,但这些只是直接的问题。我将概述为什么你不会在这里测量任何非常有用的东西。

    只有通过对代码执行进行非常详细和艰苦的分析,才能获得关于特定性能配置文件背后的实际原因的准确答案。为什么?因为它取决于影响 JVM 即时编译器复杂功能的潜在大量因素。

    但是,这是肯定的:您不会被答案所启发,因为它与您的代码没有太大关系;而是它与您选择测试它的方式有关

    只是为了感受一下您可能期望的答案:大多数优化的粒度级别是方法,并且只有在方法被证明可以进行 JIT 编译后,它才会被 JIT 编译成为热点(默认情况下,它必须累积 10,000 次调用)。所以当你把代码提取到一个方法中时,你会在编译的时候就得到好处。

    然而,还有一种栈上替换的技术,其中方法在执行时被优化。这是您在内联案例中必须依赖的。优化器将在方法中间检测到热循环并编译。但是,这是一种非常不同的机制,因此您可以期待不同的结果。

    【讨论】:

      猜你喜欢
      • 2012-02-13
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 2011-08-22
      • 2019-01-31
      • 2012-01-17
      • 2017-07-07
      • 1970-01-01
      相关资源
      最近更新 更多