Benzer bir sorum olduğu için bu bana hızlı bir başlangıç yaptı.
Benim sorum biraz daha spesifik, 'refleksif dizi uygulaması için en hızlı yöntem nedir'
Marc Gravell tarafından yapılan test çok şey gösteriyor, ancak tam olarak zamanlamaya erişmiyor. Onun zamanlaması dizi ve listeler üzerinde döngü de içerir. Ayrıca test etmek istediğim üçüncü bir yöntem bulduğumdan, sadece karşılaştırmak için bir 'Sözlük', test kodunu uzattım.
Firts, bir döngü kullanarak bir test yapıyorum, bu da bana döngü dahil belirli bir zamanlama veriyor. Bu, gerçek erişim hariç 'çıplak' bir zamanlamadır. Sonra konu yapısına erişerek bir test yapıyorum, bu bana ve 'genel gider' zamanlaması, döngü ve gerçek erişim sağlıyor.
'Çıplak' zamanlama ve 'baş üstü kapalı' zamanlama arasındaki fark bana 'yapı erişimi' zamanlamasının bir göstergesini veriyor.
Ancak bu zamanlama ne kadar doğrudur? Test sırasında pencereler shure için biraz dilimleme yapar. Zaman dilimleme hakkında hiçbir bilgim yok, ancak test sırasında ve onlarca msn sırasına eşit olarak dağıtıldığını varsayıyorum, bu da zamanlamanın doğruluğunun +/- 100 msn kadar olması gerektiği anlamına geliyor. Biraz kaba bir tahmin mi? Her neyse, sistematik bir ölçüm hatası kaynağı.
Ayrıca, testler hiçbir optimizasyon olmadan 'Hata Ayıklama' modunda yapıldı. Aksi takdirde derleyici gerçek test kodunu değiştirebilir.
Böylece, biri sabit, '(c)' olarak işaretlenmiş ve '' n '' olarak işaretlenmiş erişim için iki sonuç alıyorum ve 'dt' farkı bana gerçek erişimin ne kadar zaman aldığını anlatıyor.
İşte sonuçlar:
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
Zamanlama hataları hakkında daha iyi tahminlerle (zaman dilimlemeden dolayı sistematik ölçüm hatasının nasıl kaldırılacağı?) Sonuçlar hakkında daha fazla şey söylenebilir.
List / foreach en hızlı erişime sahip gibi görünüyor, ancak ek yükü öldürüyor.
List / for ve List / foreach arasındaki fark sabittir. Belki biraz para kazanılır?
Ayrıca, bir diziye erişim için bir for
döngü veya döngü kullanmanız önemli değildir foreach
. Zamanlama sonuçları ve kesinliği sonuçları 'karşılaştırılabilir' hale getirir.
Bir sözlük kullanmak çok yavaş, ben sadece bunu düşündüm çünkü sol tarafta (dizinleyici) ben tamsayıların bir seyrek listesi var ve bu testlerde kullanılan bir aralık değil.
İşte değiştirilmiş test kodu.
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);