2012-03-05 29 views
7

好奇心を要しないGenericListとArrayListを比較するティック数をテストしたかったのです。なぜ簡易リスト<T>はArrayListよりも遅いようですか?

ストップウォッチをチェックすると、以下のコードでArrayListが高速に見えます。

私は何か間違ったことをしているのですか、これについての説明はありますか? (私はリストのstoがはるかに速いことが考えられる)

Tesingコードと以下の出力:

private static void ArrayListVsGenericList() 
{ 
    // Measure for ArrayList 
    Stopwatch w0 = new Stopwatch(); 
    w0.Start(); 

    ArrayList aList = new ArrayList(); 

    for (int i = 0; i < 1001; i++) 
    { 
     Point p = new Point(); 
     p.X = p.Y = i; 

     aList.Add(p); 
    } 

    foreach (Point point in aList) 
    { 
     int v0 = ((Point) aList[8]).X; //unboxing 
    } 


    w0.Stop(); 

    // Measure for Generic List<Point> 
    Stopwatch w1 = new Stopwatch(); 
    w1.Start(); 

    List<Point> list = new List<Point>(); 

    for (int i = 0; i < 1001; i++) 
    { 
     Point p = new Point(); 
     p.X = p.Y = i; 

     list.Add(p); 
    } 


    foreach (var point in list) 
    { 
     int v1 = list[8].X; 
    } 

    w1.Stop(); 

    Console.WriteLine("Watch 0 : " + w0.ElapsedTicks); 
    Console.WriteLine("Watch 1 : " + w1.ElapsedTicks); 
    Console.WriteLine("Watch 0 > Watch 1 : " + (w0.ElapsedTicks > w1.ElapsedTicks)); 
} 

enter image description here

+0

私はこの試験が信頼できるとは思わない。まず、コードの実行順序が重要です。 2番目のリストに追加すると、以前の割り当てが犠牲になることがあります。また、1000個の要素は小さなセットです。 2つの異なるプログラムで2種類のリストの塗りつぶしと取り出しを分離してから、ストップウォッチではなくプロファイラーを使用してテストする必要があります。 – vulkanino

+0

''ポイント ''の代わりに '' int''を使用するとどうなりますか?最初にジェネリックリストをテストするときは? –

+0

まあ、要素数を1000001に増やすとジェネリックスが速くなりました。しかし、これは、ジェネリックスが小さなセットの要素に取り組んでいるとき、最も速く考えることができないということですか? – pencilCake

答えて

7

少なくとも二回あなたの方法を実行して、最初の実行を無視するようにテストプログラムを変更します。結果は、具体的なタイプList<Point>のコード生成とジッタによって引き起こされます。私のマシン上で

これは次の出力につながる:

Watch 0 : 154 
    Watch 1 : 74 
    Watch 0 > Watch 1 : True 

1が期待するものはかなりあります。

+0

を参照してください。 2回目の実行では、小さな要素のセットであってもずっと速かったです。 (この場合、NGENを実行する場合。EXE;私は一般的なリストのために速くなるように1回目の実行を保証します、私は仮定します) – pencilCake

5

JITのような最初の実行エフェクトを削除しませんでした。ジェネリックは、すべての値型引数に対して一度コンパイルする必要があります。

ArrayListはすでにngenでプリコンパイルされています。

List<T>は、特定のパラメータタイプに対してのみプリコンパイルされています(コアライブラリはオブジェクト、bool、intなどの一般的な引数の最も重要なジェネリックをいくつかインスタンス化します)。それで、一度の費用がかかります。

ArrayListのパフォーマンスコストのほとんどが間接的であることにも注意してください。ボクシングはGCに負担をかけ、より多くのメモリを使用します。しかし、あなたのテストはそれを測定しません。より多くのゴ​​ミを生産するコストは、他のオブジェクトがいくつ存在するか、オブジェクトの存続期間にも依存します。

テストを書くときは、実際のテストの前にすべてのコードを1回実行するか、1回のコストが無視できるほど多くの反復を使用する必要があります。リリースビルドを使用し、を実行することも重要です。デバッガにはが添付されていません。

関連する問題