class SimpleClass struct SimpleStruct
{ {
public int Value0; public int Value0;
} }
class ComplexClass struct ComplexStruct
{ {
public int Value0; public int Value0;
public int Value1; public int Value1;
public int Value2; public int Value2;
public int Value3; public int Value3;
public int Value4; public int Value4;
public int Value5; public int Value5;
public int Value6; public int Value6;
public int Value7; public int Value7;
public int Value8; public int Value8;
public int Value9; public int Value9;
public int Value10; public int Value10;
public int Value11; public int Value11;
} }
は私のマシン上で、次の興味深い結果が得られ、次のタイプに置き換え、次の短いものの、完全なプログラム例T
と
const long iterations = 1000000000;
T[] array = new T[1 << 20];
for (int i = 0; i < array.Length; i++)
{
array[i] = new T();
}
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
array[i % array.Length].Value0 = i;
}
Console.WriteLine("{0,-15} {1} {2:n0} iterations/s",
typeof(T).Name, sw.Elapsed, iterations * 1000d/sw.ElapsedMilliseconds);
とタイプのために遅いです(Windows 7 .NET 4.5 32ビット)
SimpleClass 00:00:10.4471717 95,721,260 iterations/s ComplexClass 00:00:37.8199150 26,441,736 iterations/s SimpleStruct 00:00:12.3075100 81,254,571 iterations/s ComplexStruct 00:00:32.6140182 30,661,679 iterations/s
質問1:なぜComplexClass
はSimpleClass
よりずっと遅いのですか?経過時間は、クラス内のフィールドの数に比例して増加するようです。たくさんのフィールドを持つクラスの最初のフィールドに書き込むのは、1つのフィールドしか持たないクラスの最初のフィールドに書き込むべきではないでしょうか?
質問2:なぜComplexStruct
がSimpleStruct
より遅いのですか? ILコードを見ると、i
はアレイに直接書き込まれ、ComplexStruct
のローカルインスタンスには書き込まれず、アレイにコピーされます。したがって、より多くのフィールドをコピーすることによってオーバーヘッドが発生しないはずです。
ボーナス質問:はなぜComplexClass
よりComplexStruct
速いのですか?
編集:小さなアレイと更新されたテスト結果、T[] array = new T[1 << 8];
:
SimpleClass 00:00:13.5091446 74,024,724 iterations/s ComplexClass 00:00:13.2505217 75,471,698 iterations/s SimpleStruct 00:00:14.8397693 67,389,986 iterations/s ComplexStruct 00:00:13.4821834 74,172,971 iterations/s
だから実質SimpleClass
とComplexClass
、及びSimpleStruct
とComplexStruct
の間のわずかな差との差がありません。しかし、パフォーマンスは、SimpleClass
とSimpleStruct
で大幅に減少しました。
編集:T[] array = new T[1 << 16];
とそして今:
SimpleClass 00:00:09.7477715 102,595,670 iterations/s ComplexClass 00:00:10.1279081 98,745,927 iterations/s SimpleStruct 00:00:12.1539631 82,284,210 iterations/s ComplexStruct 00:00:10.5914174 94,419,790 iterations/s
結果1<<15
ためには1<<8
のようなもので、1<<17
のための結果は1<<20
のようなものです。
あなたのCPUは、現時点ではそのキャッシュページにメモリを読み込む:1の質問へ
私は決定的な知識の答えを持つ人を聞くことに興味があります。複雑なバージョンの速度低下に寄与すると思うことの1つは、メモリからCPUキャッシュに移動する必要のあるデータ量の増加です。 – hatchet
私はCarson63000に、単純な構造と複雑な構造の違いは、複雑なタイプのキャッシュの利点が少ないことが原因であることにほとんど同意します。 struct vs classの場合、structは値型ですが、classは参照型なので、クラスとの間で余分な間接化が行われます。 –
もう一つ興味深いのは、SimpleStructがSimpleClassより速くないのはなぜですか?私はそれが最速であると予想していたでしょう。 – hatchet