为什么在本次测试中数组比字典循环150次到大小为150的数组末尾的速度快于访问相同键的150次?
我虽然是由于优化,但已将其禁用
请解释
[MethodImplAttribute(MethodImplOptions.NoOptimization)]
[Repeat(25)]
[Test]
public void DictionaryVSArray()
{
//array is faster from 0 up to 600 items;
int collectionSize = 150;
//populate array
int[] array = new int[collectionSize];
for (int i = 0; i < collectionSize; i++)
{
array[i] = i;
}
//populate dictionary
Dictionary<int, int> dictionary = new Dictionary<int, int>();
for (int i = 0; i < collectionSize; i++)
{
dictionary.Add(i, i);
}
//dictionary measurement
Stopwatch dictStopWatch = new Stopwatch();
dictStopWatch.Start();
for(int i = 0; i< collectionSize; i++)
{
var s = dictionary[collectionSize-1];
}
dictStopWatch.Stop();
TimeSpan elapsedDict = dictStopWatch.Elapsed;
//array measurement
Stopwatch arrayStopWatch = new Stopwatch();
arrayStopWatch.Start();
for (int i = 0; i < collectionSize; i++)
{
foreach (int item in array)
{
if (collectionSize-1 == item)
{
break;
}
}
}
arrayStopWatch.Stop();
TimeSpan elapsedArray = arrayStopWatch.Elapsed;
Assert.Greater(elapsedArray, elapsedDict, $"array was faster by {(elapsedDict - elapsedArray).TotalMilliseconds} miliseconds");
}
答案 0 :(得分:4)
我认为您的测试完全有缺陷,我得到相反的结果。
对于我的设置
int collectionSize = 10000;
//populate array
_array = new int[collectionSize];
for (int i = 0; i < collectionSize; i++)
{
_array[i] = i;
}
_dictionary = new Dictionary<int, int>();
for (int i = 0; i < collectionSize; i++)
{
_dictionary.Add(i, i);
}
代码
[Test("List", "", true)]
public object Test1(int[] input, int scale)
{
for (int i = 0; i < input.Length; i++)
{
foreach (int item in _array)
{
if (collectionSize - 1 == item)
{
break;
}
}
}
return null;
}
[Test("Dictionary", "", false)]
public object Test2(int[] input, int scale)
{
for (int i = 0; i < input.Length; i++)
{
var s = _dictionary[input[i]];
}
return null;
}
我每次运行100次测试,垃圾收集在每次运行之前进行一次热身运行,并生成0-255之间的1000个随机数进行测试(在发布模式下)。
┌──────────────────┬────────────────────────────────────────────┐
│ Test Mode │ Release (64Bit) │
│ Test Framework │ .NET Framework 4.7.1 (CLR 4.0.30319.42000) │
╞══════════════════╪════════════════════════════════════════════╡
│ Operating System │ Microsoft Windows 10 Pro │
│ Version │ 10.0.17134 │
├──────────────────┼────────────────────────────────────────────┤
│ CPU System │ Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz │
│ CPU Description │ Intel64 Family 6 Model 42 Stepping 7 │
├──────────────────┼──────────┬──────────────────┬──────────────┤
│ Cores (Threads) │ 4 (8) │ Architecture │ x64 │
│ Clock Speed │ 3401 MHz │ Bus Speed │ 100 MHz │
│ L2Cache │ 1 MB │ L3Cache │ 8 MB │
└──────────────────┴──────────┴──────────────────┴──────────────┘
┌── Standard input ────────────────────────────────────────────────────────┐
│ Value │ Average │ Fastest │ Cycles │ Garbage │ Test │ Gain │
├── Scale 1,000 ────────────────────────────────────────────── 0.784 sec ──┤
│ Dictionary │ 13.680 µs │ 13.208 µs │ 50.621 K │ 0.000 B │ N/A │ 99.76 % │
│ List │ 5.706 ms │ 5.485 ms │ 19.406 M │ 0.000 B │ Base │ 0.00 % │
└──────────────────────────────────────────────────────────────────────────┘
答案 1 :(得分:1)
字典有一个用于键的hastable,可以快速访问它。通过散列查找内容通常比比较内容更快。但是在您的情况下,可以快速比较整数值,并且因为您只有150 * 150个元素(22500个),所以几乎不需要时间,无论是字典还是数组。
尝试约1000 * 1000的东西。
您实际测量多少毫秒?
另外,您可能应该“搜索”循环的i值,而不总是使用相同的“ collectionSize”。也许编译器也在那里进行优化。
答案 2 :(得分:0)
在秒表中,您有一个if条件,可能在每次foreach重复开始时发生。