0

次のコードを試しました:

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.

2 番目のループは最初のループよりも時間がかからなかったようです! なぜこれが起こるのかわかりません。助けてくれてありがとう。


更新: 2 つのループを交換したので、ループ 1 の時間が短縮されました!!

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

2 に答える 2

1

正しいマイクロ ベンチマークを作成するには、非常に時間がかかり、エラーが発生しやすくなります。マイクロベンチマークは、そのために特別に設計されたCaliperなどの既に利用可能なライブラリでのみ行うことをお勧めします。

あなたのマイクロベンチマークには非常に多くの欠陥があり、予測できない結果につながります。

  1. ウォームアップを行っていません。
  2. メイン メソッド内で両方のアプローチをベンチマークしているため、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 を使用して実行すると、両方のアプローチにほぼ同じ時間がかかりますが、最適化が少し改善されます。

于 2014-02-14T09:07:48.430 に答える
0

読んだコメントから私はこのアイデアを得ました。以下のコードを試してください

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 が内部機能をウォームアップし、つま先でサービスを提供する準備ができているためです。:)

これはまた、特定のコードで使用される時間をそのアルゴリズムに直接関連付けることができないことを意味します。コードの時間消費を管理する同じ環境とパラメーターを制御する必要があります。

于 2014-02-14T07:16:43.880 に答える