C# 为什么在这个测试中数组比字典快

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;

为什么在这个测试中,数组比字典循环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");
    }
[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 % │
└──────────────────────────────────────────────────────────────────────────┘