List 与 Dictonary 在查询效率上的分界线

List 与 Dictonary 在查询效率上的分界线

在读性能分析的文章的时候,刚好见过一个提示,在小数据量的情况下,使用Dictonary会比较占用内存空间,效率上也不必List的好多少,所以建议小数据量的时候,可以使用List。

文章只是介绍细节,没有实证,因此随手写了一个demo来验证一下这个过程。

初始化的核心是List和Dictionary的长度和数据一致,作为测试用例的数据也要同一份,测试用的数据随机生成。
比较的重点在不同数据量的情况下,两种类型的查询效率之比。

int capacity = 0;
int testCount = 1000;
int idRang = 1000;

List<string> testList = new List<string>();

List<string> list = new List<string>();

Dictionary<string, string> map = new Dictionary<string, string>();

public BaseListAndDictionary(int capacity = 10)
{
    this.capacity = capacity;

    Random rand = new Random();

    for(var i = 0;i < capacity; i++)
    {
        var data = rand.Next(0, idRang).ToString();
        if(map.ContainsKey(data))
        {
            i--;
            continue;
        }

        list.Add(data);
        map[data] = data;
    }

    for(var i =0;i < idRang; i++)
    {
        testList.Add(list[rand.Next(0, idRang) % capacity]);
    }
}

List的查询用了2种方法,一种是在For循环里比对,一种使用了Linq。


[Benchmark]
public void TestListFor()
{
    for (var i = 0; i < testCount; i++)
    {
        var findItem = testList[i];
        string item = null;
        for (var j = 0; j < list.Count; j++)
        {
            if (list[j] == findItem)
            {
                item = list[j];
                break;
            }
        }
    }
}

[Benchmark]
public void TestListFirstOrDefault()
{
    for(var i =0;i < testCount; i++)
    {
        var findItem = testList[i];
        var item = list.FirstOrDefault(o=> o == findItem);
    }
}

[Benchmark]
public void TestDictionary()
{
    for (var i = 0; i < testCount; i++)
    {
        var findItem = testList[i];
        string item;
        map.TryGetValue(findItem, out item);
    }
}     

测试环境如下:

BenchmarkDotNet=v0.11.0, OS=Windows 10.0.10240.17202 (1507/RTM/Threshold1)
Intel Xeon CPU E5-1607 0 3.00GHz, 1 CPU, 4 logical and 4 physical cores
Frequency=2923049 Hz, Resolution=342.1085 ns, Timer=TSC
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
DefaultJob : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT

测试的结果数据如下:

int 5 10 20 50
TestListFor 0.0570 us 0.0447 us 0.3559 us 0.0171 us
TestListFirstOrDefault 0.2354 us 2.5835 us 5.6384 us 0.7374 us
TestDictionary 0.5711 us 0.1078 us 0.5004 us 0.0074 us
string 5 10 20 50
TestListFor 0.0115 us 0.0539 us 0.0565 us 2.0825 us
TestListFirstOrDefault 0.4236 us 0.4179 us 1.9821 us 12.9455 us
TestDictionary 0.7195 us 0.0120 us 1.4515 us 0.0343 us

结果数据的波动幅度比较大,测试了几次也是这样,可能和测试环境与测试用例的数据有关。但总体的比例关系是确定的。结论如下:

1. List用for循环查询快,Linq的FirstOrDefault是比较慢的,4~5倍的差距。
2. Dictionary在20次左右查询效率会逐渐超过List。
3. 只要不是热点函数,以及大数据(量级请自测),爱用那个用那个。
«   2023年9月   »
123
45678910
11121314151617
18192021222324
252627282930
网站分类
文章归档

Powered By Z-BlogPHP 1.6.5 Valyria

Copyright csharptools.cn Rights Reserved. 桂ICP备17007292号-1