LINQ:对LIST和Dictionary处理效率测试

LINQ:对LIST和Dictionary处理效率测试

问题

既然LINQ可以对集合进行串行处理和并行处理,究竟哪种效率更高呢?目测是并行啊。

list泛型集合。里面成装的是实体类。可以实例化。

dictionary的功能比较简单,只能算是功能强点的数组。里面储存的键值对

那么对List和Dictionary两种集合的处理,效率是否一样?

下面分别对List和Dictionary展开并行和串行处理,进行效率比较。

测试

  1. 首先我们声明1个类,RichMan,不好意思,暴露自己想法了。
 public class RichMan
 {
     public string name { get; set; }
     public int money { get; set; }
     public int Age { get; set; }
     public DateTime CreateTime { get; set; }
 }
  1. 分明产生1500w条list和Dictionary记录:
 public static ConcurrentDictionary<int, RichMan> LoadData()
 {
 	//这里采用并行字典,确保LINQ并行计算时不会报错
     ConcurrentDictionary<int, RichMan> dic = new ConcurrentDictionary<int, RichMan>();

     //预加载1500w条记录
     Parallel.For(0, 15000000, (i) =>
     {
         var single = new RichMan()
         {
             money = i,
             name = "qcj" + i,
             Age = i % 200,
             CreateTime = DateTime.Now.AddSeconds(i)
         };
         dic.TryAdd(i, single);
     });
     return dic;
 }

 public static List<RichMan> LoadListData()
 {
     List<RichMan> list = new List<RichMan>();

     //预加载1500w条记录
     for (int i = 0; i < 15000000; i++)
     {
         RichMan single = new RichMan()
         {
             name = "qcj" + i,
             money =   i,
             Age = i % 200,
             CreateTime = DateTime.Now.AddSeconds(i)
         };
         list.Add(single);
     }
     return list;
 }
  1. 测试,4种方法依次来一遍:
 static void Main(string[] args)
 {
     var dict = LoadData();
     Stopwatch watch = new Stopwatch();
     watch.Start();

     //Dictionary串行执行
     var query1 = (from n in dict.Values
                   where n.Age > 25 && n.Age < 30
                   select n).ToList();

     watch.Stop();
     Console.WriteLine("串行计算Dictionary耗费时间:{0}", watch.ElapsedMilliseconds);
     watch.Restart();

	//Dictionary并行执行
     var query2 = (from n in dict.Values.AsParallel()
                   where n.Age > 25 && n.Age < 30
                   select n).ToList();

     watch.Stop();
     Console.WriteLine("并行Dictionary计算耗费时间:{0}", watch.ElapsedMilliseconds);

     //查询list
     var list = LoadListData();
     watch.Restart();

     //list串行执行
     var query3 = (from n in list
                   where n.Age > 25 && n.Age < 30
                   select n).ToList();

     watch.Stop();
     Console.WriteLine("串行List计算耗费时间:{0}", watch.ElapsedMilliseconds);
     watch.Restart();

	//list并行执行
     var query4 = (from n in list.AsParallel()
                   where n.Age > 25 && n.Age < 30
                   select n).ToList();

     watch.Stop();
     Console.WriteLine("并行List计算耗费时间:{0}", watch.ElapsedMilliseconds);
     Console.Read();
 }
  1. 结果如下
    在这里插入图片描述

结果可以发现,linq并行计算效率明显高于串行计算,list并行计算最快

问题剖析:

参考了 这篇文章.

同样是集合,为什么性能会有这样的差距。我们要从存储结构和操作系统的原理谈起。

首先我们清楚List是对数组做了一层包装,我们在数据结构上称之为线性表,而线性表的概念是,在内存中的连续区域,除了首节点和尾节点外,每个节点都有着其唯一的前驱结点和后续节点。我们在这里关注的是连续这个概念。

而HashTable或者Dictionary,他是根据Key而根据Hash算法分析产生的内存地址,因此在宏观上是不连续的,虽然微软对其算法也进行了很大的优化。

由于这样的不连续,在遍历时,Dictionary必然会产生大量的内存换页操作,而List只需要进行最少的内存换页即可,这就是List和Dictionary在遍历时效率差异的根本原因。

在这里我们除了刚才的遍历问题,还要提到Dictionary的存储空间问题,在Dictionary中,除了要存储我们实际需要的Value外,还需要一个辅助变量Key,这就造成了内存空间的双重浪费。

而且在尾部插入时,List只需要在其原有的地址基础上向后延续存储即可,而Dictionary却需要经过复杂的Hash计算,这也是性能损耗的地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值