비슷한 질문이 있었으므로 빠른 시작이되었습니다.
제 질문은 좀 더 구체적입니다. '반사 배열 구현을위한 가장 빠른 방법은 무엇입니까?'
Marc Gravell이 수행 한 테스트 결과는 많지만 액세스 타이밍이 정확하지는 않습니다. 그의 타이밍에는 배열과 목록에 대한 루핑이 포함됩니다. 또한 테스트하려는 세 번째 방법 인 '사전'을 비교하기 위해 hist 테스트 코드를 확장했습니다.
Firts, 상수를 사용하여 테스트를 수행하면 루프를 포함한 특정 타이밍을 얻을 수 있습니다. 실제 액세스를 제외한 '베 어린'타이밍입니다. 그런 다음 주제 구조에 액세스하여 테스트를 수행하면 '오버 헤드 포함'시간, 루프 및 실제 액세스가 제공됩니다.
'베어'타이밍과 '오버 헤드 통합'타이밍의 차이는 '구조 액세스'타이밍을 나타냅니다.
그러나이 타이밍은 얼마나 정확합니까? 테스트 기간 동안 창은 슈어를 위해 약간의 시간 슬라이싱을 수행합니다. 시간 슬라이싱에 대한 정보는 없지만 테스트 중에 수십 msec의 순서로 균등하게 분배된다고 가정합니다. 즉, 타이밍의 정확도는 +/- 100 msec 정도 여야합니다. 약간의 추정치? 어쨌든 체계적인 측정 오류의 원인.
또한 테스트는 최적화없이 '디버그'모드에서 수행되었습니다. 그렇지 않으면 컴파일러가 실제 테스트 코드를 변경할 수 있습니다.
따라서 두 개의 결과를 얻습니다. 하나는 상수이고 '(c)'로 표시된 것과 하나는 '(n)'으로 표시된 액세스에 대한 것입니다. 차이 'dt'는 실제 액세스에 걸리는 시간을 알려줍니다.
그리고 이것은 결과입니다 :
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
타이밍 오류 (시간 슬라이싱으로 인한 체계적인 측정 오류를 제거하는 방법)에 대한 더 나은 추정치가 있으면 결과에 대해 더 많이 말할 수 있습니다.
List / foreach가 가장 빠른 액세스 권한을 가진 것처럼 보이지만 오버 헤드가이를 죽이고 있습니다.
List / for와 List / foreach의 차이점은 정체입니다. 어쩌면 현금이 필요할까요?
또한 배열에 액세스하기 위해 for
루프 또는 루프 를 사용하더라도 중요하지 않습니다 foreach
. 타이밍 결과와 정확도는 결과를 '비교적'으로 만듭니다.
사전을 사용하는 것이 훨씬 느리다. 왼쪽 (인덱서)에는 정수의 스파 스 목록이 있고이 테스트에서 사용되는 범위가 아니기 때문에 사전을 고려했습니다.
다음은 수정 된 테스트 코드입니다.
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);