小さなベンチマーキング配列に対すリストのJava:私のベンチマーキングコードが悪いのでしょうか。

StackOverflow https://stackoverflow.com/questions/2227947

質問

免責事項: していました この 質問この質問 どちらもっと脱線による小 詳細および一般 最適化は不要です。私は本当に必要なすべての機能I できる現在のアプリは、 受信-処理-噴き出MIDIデータ リアルタイム.また、ニーズにスケールアップ とが可能です。

私の比較 array パフォーマンスの高い番号の読み込みのための小型のリスト ArrayList もうこの変数です。私はこの配列ビート ArrayList 効果を明確にする必要がある2.5 でもビートだけのオブジェクト参照です。

何を知りたいと思い:

  1. 私のベンチマークには免許が必要です。 思い切り替えを順この試験運行回数の変更.私もミリ秒単位ではなくナノ秒に無い.
  2. べきかを指定する任意のJavaオプションをこの違いは?
  3. この違いのですが、この場合に なります。 Test[]ArrayList<Test> このコードに必要な変換ですか。 明らかにいくつかについて触れたいと思いくよ。

JVMがJava1.6.0_17にOSXでは走行でのホットスポットモードになります。

  public class ArraysVsLists {

    static int RUNS = 100000;

    public static void main(String[] args) {
        long t1;
        long t2;

        Test test1 = new Test();
        test1.thing = (int)Math.round(100*Math.random());
        Test test2 = new Test();
        test2.thing = (int)Math.round(100*Math.random());

        t1 = System.nanoTime();

        for (int i=0; i<RUNS; i++) {
            test1.changeThing(i);
            test2.changeThing(i);
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1) + " How long NO collection");

        ArrayList<Test> list = new ArrayList<Test>(1);
        list.add(test1);
        list.add(test2);
        // tried this too: helps a tiny tiny bit 
        list.trimToSize();

        t1= System.nanoTime();

        for (int i=0; i<RUNS; i++) {
            for (Test eachTest : list) {
                eachTest.changeThing(i);
            }
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1) + " How long collection");


        Test[] array = new Test[2];
        list.toArray(array);

        t1= System.nanoTime();

        for (int i=0; i<RUNS; i++) {
            for (Test test : array) {
                test.changeThing(i);
            }
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1) + " How long array ");

    }
}

class Test {
    int thing;
    int thing2;
    public void changeThing(int addThis) {
        thing2 = addThis + thing;
    }
}
役に立ちましたか?

解決

Microbenchmarksは非常に硬く、プラットフォーム上のようにJava.すべてのコードに照らして評価される別の方法、走らせることにより、数千回としてウォームアップします。もちろん、このコード下記の結果は直接アクセスを通じて参考文献はその三倍の速度を通じて配列がコレクションはまだ鈍化効果を明確にする必要がある2.

これらの数のJVMのオプション -server -XX:+DoEscapeAnalysis.なし -server, は、コレクションは を大幅に 遅くなり(不思議とは、配列アクセスはかなり速くすることを示すものがありかえします。 -XX:+DoEscapeAnalysis 利回り30%短縮のためのコレクションでもquestionabledるかどうかでも実際の生産コードです。

全体的に私の結論することはできない。忘れmicrobenchmarksでも簡単に誤解を招くものであると述べた。対策として近いプロダクションコードとしてできなく書き換え全願います。

import java.util.ArrayList;

public class ArrayTest {

    static int RUNS_INNER = 1000;
    static int RUNS_WARMUP = 10000;
    static int RUNS_OUTER = 100000;

    public static void main(String[] args) {
        long t1;
        long t2;

        Test test1 = new Test();
        test1.thing = (int)Math.round(100*Math.random());
        Test test2 = new Test();
        test2.thing = (int)Math.round(100*Math.random());

        for(int i=0; i<RUNS_WARMUP; i++)
        {
            testRefs(test1, test2);            
        }
        t1 = System.nanoTime();
        for(int i=0; i<RUNS_OUTER; i++)
        {
            testRefs(test1, test2);            
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1)/1000000.0 + " How long NO collection");

        ArrayList<Test> list = new ArrayList<Test>(1);
        list.add(test1);
        list.add(test2);
        // tried this too: helps a tiny tiny bit 
        list.trimToSize();

        for(int i=0; i<RUNS_WARMUP; i++)
        {
            testColl(list);
        }
        t1= System.nanoTime();

        for(int i=0; i<RUNS_OUTER; i++)
        {
            testColl(list);
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1)/1000000.0 + " How long collection");


        Test[] array = new Test[2];
        list.toArray(array);

        for(int i=0; i<RUNS_WARMUP; i++)
        {
            testArr(array);            
        }
        t1= System.nanoTime();

        for(int i=0; i<RUNS_OUTER; i++)
        {
            testArr(array);
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1)/1000000.0 + " How long array ");

    }

    private static void testArr(Test[] array)
    {
        for (int i=0; i<RUNS_INNER; i++) {
            for (Test test : array) {
                test.changeThing(i);
            }
        }
    }

    private static void testColl(ArrayList<Test> list)
    {
        for (int i=0; i<RUNS_INNER; i++) {
            for (Test eachTest : list) {
                eachTest.changeThing(i);
            }
        }
    }

    private static void testRefs(Test test1, Test test2)
    {
        for (int i=0; i<RUNS_INNER; i++) {
            test1.changeThing(i);
            test2.changeThing(i);
        }
    }
}

class Test {
    int thing;
    int thing2;
    public void changeThing(int addThis) {
        thing2 = addThis + thing;
    }
}

他のヒント

ごベンチマークが有効な場合は、実使用の場合、ベンチマークコードする非常に少数の事業を各要素に、実行時間が大きく決定アクセス時間による操作です。なお、この場合にはその使用の配列の場合の性能は重要である。がしかしながら、お客様の実利用の場合については、これまでより実際の計算の一要素にアクセス時間の要素となるもしくは大きい。

で有効ではありません。理解している方法JITコンパイラでコンパイル作業をコンパイル方法な影響を呼び出する方法はないことがある。以降、 main 方法でのみ呼び出すことで、結果解釈され、多くの作業をする方法、お得な特定通常実行します。

JITコ影響があるのかな回収場合が遅かったの配列。この結果は、あくまでもカウンター-直感的で、とくに違いはその他のベンチマーク結果のご報告する。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top