Da ich eine ähnliche Frage hatte, bekam ich einen schnellen Start.
Meine Frage ist etwas spezifischer: Was ist die schnellste Methode für eine reflexive Array-Implementierung?
Die von Marc Gravell durchgeführten Tests zeigen viel, aber nicht genau das Timing des Zugriffs. Sein Timing beinhaltet auch das Durchlaufen der Arrays und Listen. Da ich auch eine dritte Methode gefunden habe, die ich testen wollte, ein 'Wörterbuch', um sie zu vergleichen, habe ich den Hist-Testcode erweitert.
Firts, ich mache einen Test mit einer Konstanten, die mir ein bestimmtes Timing einschließlich der Schleife gibt. Dies ist ein "nackter" Zeitpunkt, der den tatsächlichen Zugriff ausschließt. Dann mache ich einen Test mit Zugriff auf die Subjektstruktur, dies gibt mir und Overhead inklusive Timing, Looping und tatsächlichen Zugriff.
Der Unterschied zwischen "nacktem" Timing und "Overhead-eingeschlossenem" Timing gibt mir einen Hinweis auf das "Strukturzugriff" -Zeitpunkt.
Aber wie genau ist dieses Timing? Während des Tests werden die Fenster einige Zeit in Scheiben geschnitten, um die Sicherheit zu gewährleisten. Ich habe keine Informationen über das Time Slicing, aber ich gehe davon aus, dass es während des Tests gleichmäßig verteilt ist und in der Größenordnung von zehn ms liegt, was bedeutet, dass die Genauigkeit für das Timing in der Größenordnung von +/- 100 ms oder so liegen sollte. Eine etwas grobe Schätzung? Auf jeden Fall eine Quelle für einen systematischen Mearure-Fehler.
Außerdem wurden die Tests im Debug-Modus ohne Optimierung durchgeführt. Andernfalls kann der Compiler den tatsächlichen Testcode ändern.
Ich erhalte also zwei Ergebnisse, eines für eine Konstante mit der Bezeichnung '(c)' und eines für den mit '(n)' gekennzeichneten Zugriff. Die Differenz 'dt' gibt an, wie viel Zeit der tatsächliche Zugriff benötigt.
Und das sind die Ergebnisse:
Dictionary(c)/for: 1205ms (600000000)
Dictionary(n)/for: 8046ms (589725196)
dt = 6841
List(c)/for: 1186ms (1189725196)
List(n)/for: 2475ms (1779450392)
dt = 1289
Array(c)/for: 1019ms (600000000)
Array(n)/for: 1266ms (589725196)
dt = 247
Dictionary[key](c)/foreach: 2738ms (600000000)
Dictionary[key](n)/foreach: 10017ms (589725196)
dt = 7279
List(c)/foreach: 2480ms (600000000)
List(n)/foreach: 2658ms (589725196)
dt = 178
Array(c)/foreach: 1300ms (600000000)
Array(n)/foreach: 1592ms (589725196)
dt = 292
dt +/-.1 sec for foreach
Dictionary 6.8 7.3
List 1.3 0.2
Array 0.2 0.3
Same test, different system:
dt +/- .1 sec for foreach
Dictionary 14.4 12.0
List 1.7 0.1
Array 0.5 0.7
Mit besseren Schätzungen der Zeitfehler (wie kann der systematische Messfehler aufgrund von Zeitscheiben beseitigt werden?) Könnte mehr über die Ergebnisse gesagt werden.
Es sieht so aus, als hätte List / foreach den schnellsten Zugriff, aber der Overhead bringt ihn um.
Der Unterschied zwischen List / for und List / foreach ist seltsam. Vielleicht ist etwas Geld erforderlich?
Für den Zugriff auf ein Array spielt es keine Rolle, ob Sie eine for
Schleife oder eine foreach
Schleife verwenden. Die Timing-Ergebnisse und ihre Genauigkeit machen die Ergebnisse "vergleichbar".
Die Verwendung eines Wörterbuchs ist bei weitem am langsamsten. Ich habe es nur in Betracht gezogen, weil ich auf der linken Seite (dem Indexer) eine spärliche Liste von Ganzzahlen habe und keinen Bereich, wie er in diesen Tests verwendet wird.
Hier ist der geänderte Testcode.
Dictionary<int, int> dict = new Dictionary<int, int>(6000000);
List<int> list = new List<int>(6000000);
Random rand = new Random(12345);
for (int i = 0; i < 6000000; i++)
{
int n = rand.Next(5000);
dict.Add(i, n);
list.Add(n);
}
int[] arr = list.ToArray();
int chk = 0;
Stopwatch watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = dict.Count;
for (int i = 0; i < len; i++)
{
chk += 1; // dict[i];
}
}
watch.Stop();
long c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Dictionary(c)/for: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = dict.Count;
for (int i = 0; i < len; i++)
{
chk += dict[i];
}
}
watch.Stop();
long n_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Dictionary(n)/for: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = list.Count;
for (int i = 0; i < len; i++)
{
chk += 1; // list[i];
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(c)/for: {0}ms ({1})", c_dt, chk);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = list.Count;
for (int i = 0; i < len; i++)
{
chk += list[i];
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(n)/for: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
for (int i = 0; i < arr.Length; i++)
{
chk += 1; // arr[i];
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Array(c)/for: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
for (int i = 0; i < arr.Length; i++)
{
chk += arr[i];
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Array(n)/for: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in dict.Keys)
{
chk += 1; // dict[i]; ;
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Dictionary[key](c)/foreach: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in dict.Keys)
{
chk += dict[i]; ;
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Dictionary[key](n)/foreach: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in list)
{
chk += 1; // i;
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(c)/foreach: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in list)
{
chk += i;
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(n)/foreach: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in arr)
{
chk += 1; // i;
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Array(c)/foreach: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in arr)
{
chk += i;
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Array(n)/foreach: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);