为什么单独的方法比内联的相同代码更快

时间:2014-10-22 14:08:30

标签: java methods coding-style inline-code

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

  Max generated: 999999
  Max is 999999  Time consumed main: 1.8210982999999998 ms
  Max is 999999 Time consumed method: 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;
    }
}

2 个答案:

答案 0 :(得分: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);

这将只计算方法中所用的时间。

答案 1 :(得分:1)

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

只有通过对代码执行的非常详细和细致的分析,才能获得关于某个性能配置文件背后的实际原因的准确答案。为什么?因为它依赖于可能影响JVM即时编译器复杂功能的大量因素。

然而,这是肯定的:你不会被答案所启发,因为它与你的代码没有多大关系;相反,它将与确切地选择如何测试相关。

只是为了感受一下您可能期望的答案:大多数优化的粒度级别是方法,并且只有在经过验证后才能对方法进行JIT编译。是一个热点(默认情况下,它将累积10,000次调用)。因此,当您将代码提取到某个方法时,只要执行该编译,您就会收到编译的好处。

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