为什么第一次在Java中调用方法时会出现运行时开销?

时间:2016-12-05 03:54:36

标签: java performance main execution-time

我正在测量代码的执行时间,并在第一次调用方法时发现了一些奇怪的行为(来自main方法)。这是我的代码,请看看这个

public static void main(String[] args) {
    try (Scanner input = new Scanner(System.in)) {
        int iNum = input.nextInt();
        long lStartTime = System.nanoTime();

        // ***********(First call in main) Calling isPrime *************

        lStartTime = System.nanoTime();
        printResult(isPrime(iNum));
        System.out.println("Time Consumed in first call-: " 
                + (System.nanoTime() - lStartTime));

        // ***********(Second call in main) Calling isPrime *************
        lStartTime = System.nanoTime();
        printResult(isPrime(iNum));
        System.out.println("Time Consumed in second call-: "
                + (System.nanoTime() - lStartTime));
    }
}

private static boolean isPrime(int iNum) {
    boolean bResult = true;

    if (iNum <= 1 || iNum != 2 && iNum % 2 == 0) {
        bResult = false;
    } else {
        double iSqrt = Math.sqrt((double) iNum);
        for (int i = 3; i < iSqrt; i += 2) {
            if (iNum % i == 0) {
                bResult = false;
                break;
            }
        }
    }
    return bResult;
}

private static void printResult(boolean bResult) {
    if (bResult)
        System.out.println("\nIt's prime number.");
    else
        System.out.println("\nIt's not prime number.");
}

输入

5

输出

It's prime number.
Time Consumed in first call-: 484073

It's prime number.
Time Consumed in second call-: 40710

描述

我上面只描述了一个输入和输出的测试用例。但是,第一个方法调用和第二个方法调用之间的执行时间总是存在差异。

我也以类似的方式尝试了两个以上的方法调用,发现除了一个调用之外,其他调用之间没有这么大的差别。除了第一个方法调用 484073ns 之外,其他调用的执行时间 40710ns (此系统的执行时间可能会有所不同)。很容易我在第一次方法调用中看到 484073 - 40710 = 443363ns (大约)的时间开销,但为什么会发生?根本原因是什么?

1 个答案:

答案 0 :(得分:1)

Java Runtime Environment有多种实现方式,因此并非每个实现都可能像Oracle(以及之前的Sun)一样。

开头说,在大多数当前实现中,方法的初始调用涉及验证和Java字节码的首次编译。因此,该方法的后续调用更快。但是,Java也使用JIT。维基百科在Just-in-time compilation上提供了一个注释

的条目
  

由于加载和编译字节码所花费的时间,JIT会导致应用程序初始执行时出现明显延迟。

接着说,

  

最初解释应用程序代码,但JVM监视频繁执行哪些字节码序列,并将它们转换为机器代码,以便在硬件上直接执行。