C# 为什么在这个测试中数组比字典快
为什么在这个测试中,数组比字典循环150倍到大小为150的数组末尾的速度快,比访问同一个键快150倍 我认为这是由于优化,但我已禁用它 请解释一下C# 为什么在这个测试中数组比字典快,c#,performance,nunit,C#,Performance,Nunit,为什么在这个测试中,数组比字典循环150倍到大小为150的数组末尾的速度快,比访问同一个键快150倍 我认为这是由于优化,但我已禁用它 请解释一下 [MethodImplAttribute(MethodImplOptions.NoOptimization)] [Repeat(25)] [Test] public void DictionaryVSArray() { //array is faster from 0 up to 600 items;
[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");
}
[MethodImplAttribute(MethodImplOptions.NoOptimization)]
[重复(25)]
[测试]
公共无效字典yvsarray()
{
//数组速度更快,从0到600项;
int collectionSize=150;
//填充数组
int[]数组=新的int[collectionSize];
对于(int i=0;i
字典有一个快捷键表,可以快速访问。通过散列查找内容比比较内容要快得多。但在您的例子中,整数值会很快进行比较,因为您只有150*150个元素(22500),这几乎不需要时间,无论是字典还是数组
试试1000*1000左右的东西
你实际测量了多少毫秒
此外,您还应该“搜索”循环的i值,而不是总是使用相同的“collectionSize”。也许编译器也在那里进行优化。字典有一个键的hastable,可以快速访问它。通过散列查找内容比比较内容要快得多。但在您的例子中,整数值会很快进行比较,因为您只有150*150个元素(22500),这几乎不需要时间,无论是字典还是数组 试试1000*1000左右的东西 你实际测量了多少毫秒
此外,您还应该“搜索”循环的i值,而不是总是使用相同的“collectionSize”。可能编译器也在那里进行优化。在secound stopwatch中,在开始foreach重复时可能出现if条件。在secound stopwatch中,在开始foreach重复时可能出现if条件。我认为您的测试完全有缺陷,我得到了相反的结果 对于我的设置
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);
}
后果
我认为你的测试完全有缺陷,我得到了相反的结果 对于我的设置
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);
}
后果
尝试使用字符串数组/字典。-在这里,你会看到一些非常不同的地方。Int比较很快,但string不是。但是,150 X 150循环与150个键访问?即使关闭所有优化,抖动仍然会为数组循环生成高效代码。我认为哈希生成计算比迭代150个元素慢,这就是原因why@IronHide,
int
s没有哈希计算,int
值本身就是它的哈希代码。请尝试使用字符串数组/字典。-在这里,你会看到一些非常不同的地方。Int比较很快,但string不是。但是,150 X 150循环与150个键访问?即使关闭所有优化,抖动仍然会为数组循环生成高效代码。我认为哈希生成计算比迭代150个元素慢,这就是原因why@IronHide,int
s没有哈希计算,int
值本身就是它的散列码。如您所见,优化被禁用。如您所见,优化被禁用。如您所见,优化被禁用,如您所见,如您所见,如您所见,如您所见,方法头。当然,如果有更多的元素,但数组低于150,则情况并非如此wins@IronHide我用100个元素运行相同的测试,它的使用速度更快一本字典,即使有10个元素也可以复制。你基本上有相同的测试,但在较小的集合中没有观察到这个问题?很有趣,但我在你的测试中没有看到秒表,也许可以把它们放在测试方法中,以确保相同test@IronHide嗨,我使用基准测试库,这是最可靠的测试方法。看看BenchmarkDotNet,几个小时的乐趣当然,如果有更多的元素,但低于150个数组,情况就不是这样了wins@IronHide我用100个元素和它的因子运行相同的测试,使用字典更快,即使有10个元素,它也是可复制的。所以基本上你有相同的测试,但在较小的集合中没有观察到问题?很有趣,但我在你的测试中没有看到秒表,也许可以把它们放在测试方法中,以确保相同test@IronHide嗨,我使用基准测试库,这是最可靠的测试方法。看看BenchmarkDotNet,几个小时的乐趣
┌──────────────────┬────────────────────────────────────────────┐
│ 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 % │
└──────────────────────────────────────────────────────────────────────────┘