2016-08-09 3 views
-2

[編集3 ...]int.CompareToのパフォーマンスのバリエーション

偽:テストを壊した私のオリジナルコードが使用されたループ。以下のコードでは明らかです...結局のところ "大きな"違いはありません。ただ、...

int[] arr; 
int j, comp; 

comp = j.CompareTo(arr[j]); 
comp = arr[j].CompareTo(j); 

「同じ」比較のバージョンを逆転さ:

は、私はもともと私がのCompareToのこれら二つの形式の間の性能に大きな差を見たと思いました! --- Arrayの代わりにListを使っても同じことを試みました。

私の元のコードでは、ループで別の方法でロードすることで、テストで問題が発生しました。調整されたテストは以下の通りです。それは私が見たと思った "巨大な"違いを示していません。

私はまた、リストはボクシングとunboxingを導入したと信じて...私はそれを学ぶためにILコードを調べます。

第1のペアの2つのフォームと第2のペアの2つのフォームの間には依然として差があります。このコードは非常に似ていますが、異なるIL出力を生成するので、少し興味があります。あなたはまだ読んでいる場合は

static void Main() { 
    Stopwatch stopwatch = new Stopwatch(); 
    int iterations = 100000000; 
    int comp = 0, accessIndex = 50, arg = 0; 
    List<int> list = new List<int>(100); 
    int[] arr = new int[100]; 
    for (int i = 0, j = 0; j < 100; i+=2, j++) { 
     list.Add(i); 
     arr[j] = i; 
    } 

    Console.WriteLine("int.CompareTo(List<int>[]) (Unboxing?)"); 
    stopwatch.Reset(); 
    stopwatch.Start(); 
    for (int i = 0; i < iterations; i++) { 
     comp = arg.CompareTo(list[accessIndex]); 
    } 
    stopwatch.Stop(); 
    Console.WriteLine(stopwatch.ElapsedTicks); 
    Console.WriteLine(); 

    Console.WriteLine("List<int>[].CompareTo(int) (Boxing?)"); 
    stopwatch.Reset(); 
    stopwatch.Start(); 
    for (int i = 0; i < iterations; i++) { 
     comp = list[accessIndex].CompareTo(arg); 
    } 
    stopwatch.Stop(); 
    Console.WriteLine(stopwatch.ElapsedTicks); 
    Console.WriteLine(); 

    Console.WriteLine("int.CompareTo(Array<int>[])"); 
    stopwatch.Reset(); 
    stopwatch.Start(); 
    for (int i = 0; i < iterations; i++) { 
     comp = arg.CompareTo(arr[accessIndex]); 
    } 
    stopwatch.Stop(); 
    Console.WriteLine(stopwatch.ElapsedTicks); 
    Console.WriteLine(); 

    Console.WriteLine("Array<int>[].CompareTo(int)"); 
    stopwatch.Reset(); 
    stopwatch.Start(); 
    for (int i = 0; i < iterations; i++) { 
     comp = arr[accessIndex].CompareTo(arg); 
    } 
    stopwatch.Stop(); 
    Console.WriteLine(stopwatch.ElapsedTicks); 
    Console.WriteLine(); 
} 

:最後のペアでのILコードの違い(と

int.CompareTo(List<int>[]) (Unboxing?) 
337095 

List<int>[].CompareTo(int) (Boxing?) 
375601 

int.CompareTo(Array<int>[]) 
157093 

Array<int>[].CompareTo(int) 
135420 

新しいコードを:ストップウォッチで

は私が得る私のマシン上で、ダニアレイ)のみループの先頭にある:

"int.CompareTo(配列[])" ==

// loop start (head: IL_0115) 
IL_0103: ldloca.s comp 
IL_0105: ldloc.s arr 
IL_0107: ldloc.3 
IL_0108: ldelem.i4 
IL_0109: call instance int32 [mscorlib]System.Int32::CompareTo(int32) 

"アレイ[]。のCompareTo(int型)" ==

// loop start (head: IL_0160) 
IL_014b: ldloc.s arr 
IL_014d: ldloc.3 
IL_014e: ldelema [mscorlib]System.Int32 
IL_0153: ldloc.2 
IL_0154: call instance int32 [mscorlib]System.Int32::CompareTo(int32) 

し、リストのバージョンでは、私はILのいずれかのボクシングを参照してくださいしないでください!

+1

数字(1000万回の操作あたりのティック)を数値に入力してください。そうしないと、結果はスループット(1秒あたりの処理数)と混同されやすくなります。 –

+2

あなたはVSなしでリリースでコードを実行しましたか(たとえば、cmdからexeを起動しました)。それに応じて結果は本当に違うかもしれません。また、コードを逆コンパイルして、ILを見てみてください(または、人が自分でやるのを避けるためにポストに貼り付けてください)。実際に何が起こっているのかについての情報が必要です。 – Sehnsucht

+0

デバッガーなしでリリースすることを想定しています添付されている1つの問題は、リストのCountに対して配列のループをチェックすることです。私はこれがJITの境界チェックを無効にする能力と恐らくプロセッサキャッシュを無効にすることになると確信しています。 –

答えて

-2

偽物!

私が使用したループでは、私のオリジナルコードテストが問題でした...。編集されたコードはかなり一貫した結果を示しています...そしてILは明らかに見えます。

関連する問題