簡體   English   中英

為什么調用一個函數比不調用一個函數要快?

[英]Why is calling a function faster than not calling a function?

我嘗試了以下代碼:

public class Test {
    public static void main(String[] args) {
        int x = 9, y = 9, z = 0;
        long startTime = System.currentTimeMillis();
        // System.out.println("loop one start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
            }
        }
        System.out.println("loop one use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z);

        startTime = System.currentTimeMillis();
        // System.out.println("loop two start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = sum(x, y);
            }
        }
        System.out.println("loop two use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z);

    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

控制台的輸出為:

loop one use time = 216,z = 18
loop two use time = 70,z = 18.

看來第二個循環比第一個循環花費的時間更少! 我不明白為什么會這樣。 感謝您的幫助。


更新:我交換了兩個循環,現在循環一會花費更少的時間!

loop two use time = 219,z = 18
loop one use time = 69,z = 18

編寫正確的微基准測試非常耗時且容易出錯。 我建議僅使用像Caliper這樣已經可用的庫來進行微基准測試。

您的微基准測試有很多缺陷,將導致無法預測的結果:

  1. 您沒有做任何熱身。
  2. 您正在對main方法中的這兩種方法進行基准測試,從而使JIT編譯器更難以優化代碼。
  3. 代碼“ z = x + y;” 實際上降到了“ z = 9 + 9;” 並且在循環過程中不會改變,因此可以將循環完全優化為簡單表達式“ z = 18”。

無論如何,這是使用Caliper進行相應基准測試的代碼:

@VmOptions("-server")
public class Test {

    @Benchmark
    public int timeSum1(long reps) {
        int dummy = 0; 
        int x = 9, y = 9;
        for (int j = 0; j < reps; j++) {
            dummy = x + y;
        }
        return dummy;
    }

    @Benchmark
    public int timeSum2(long reps) {
        int dummy = 0; 
        int x = 9, y = 9;
        for (int j = 0; j < reps; j++) {
            dummy = sum(x, y);
        }
        return dummy;
    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

您可以在此處查看該基准測試的結果:

結果與預期的一樣:兩種方法大約需要相同的時間,因為JIT編譯器可以內聯它們。 使用-server運行這兩種方法仍需花費大約相同的時間,但在優化方面要好一些。

從閱讀評論中我有這個想法,請嘗試以下代碼

public class Test {
    public static void main(String[] args) {
        int x = 9, y = 9, z = 0;
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
                // z = sum(x, y);
            }
        }
        long startTime = System.currentTimeMillis();
        // System.out.println("loop one start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
            }
        }
        System.out.println("loop one use time = "
                + (System.currentTimeMillis() - startTime) + ",z = " + z);

        startTime = System.currentTimeMillis();
        // System.out.println("loop two start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = sum(x, y);
            }
        }
        System.out.println("loop two use time = "
                + (System.currentTimeMillis() - startTime) + ",z = " + z);

    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

結果將表明兩個循環具有相同的時間,這是因為JVM已經預熱了其內部功能並准備好使用自己的腳趾。 :)

這也意味着您不能直接關聯某些代碼所使用的時間與其算法直接相關,因此您需要控制相同的環境和參數來控制代碼的時間消耗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM