Die folgende kurze aber vollständige BeispielprogrammFeldzugriff über Array ist langsamer für Typen mit mehreren Feldern
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);
mit T
durch folgende Typen ersetzt
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;
} }
folgende interessante Ergebnisse auf meiner Maschine ergibt (Windows 7 .NET 4.5 32-Bit)
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
Frage 1: Warum ist ComplexClass
so viel langsamer als SimpleClass
? Die verstrichene Zeit scheint linear mit der Anzahl der Felder in der Klasse zu steigen. Das Schreiben in das erste Feld einer Klasse mit vielen Feldern sollte nicht viel anders sein als das Schreiben in das erste Feld einer Klasse mit nur einem Feld, nein?
Frage 2: Warum ist ComplexStruct
langsamer als SimpleStruct
? Ein Blick auf den IL-Code zeigt, dass i
direkt in das Array geschrieben wird, nicht in eine lokale Instanz von ComplexStruct
, die dann in das Array kopiert wird. Es sollte also keinen Overhead geben, der durch das Kopieren weiterer Felder verursacht wird.
Bonusfrage: Warum ist ComplexStruct
schneller als ComplexClass
?
Edit: Aktualisiert Testergebnisse mit einem kleineren Array, 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
So praktisch keinen Unterschied zwischen SimpleClass
und ComplexClass
, und nur ein kleiner Unterschied zwischen SimpleStruct
und ComplexStruct
. Die Leistung ist jedoch für SimpleClass
und SimpleStruct
deutlich gesunken.
Edit: Und jetzt mit 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
Das Ergebnis für 1<<15
ist wie 1<<8
und das Ergebnis für 1<<17
ist wie 1<<20
.
Ich bin daran interessiert, jemanden mit definitivem Wissen zu hören. Eine Sache, von der ich denke, dass sie dazu beitragen wird, dass die komplexen Versionen langsamer werden, ist die erhöhte Datenmenge, die vom Speicher in den CPU-Cache verschoben werden muss. – hatchet
Ich stimme Carson63000, dass der Unterschied zwischen den einfachen und komplexen Strukturen fast sicher durch weniger Cache-Vorteil für die komplexen Typen verursacht wird. Wie bei struct vs. class ist struct ein Werttyp, wohingegen class ein Referenztyp ist, so dass es eine zusätzliche Indirektion für Klassen gibt. –
Eine weitere interessante Frage ist, warum ist SimpleStruct NICHT schneller als SimpleClass? Ich hätte erwartet, dass das der Schnellste ist. – hatchet