博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对《LINQ能不能用系列(一)数组筛选效率对比》中测试的几个问题
阅读量:6274 次
发布时间:2019-06-22

本文共 3761 字,大约阅读时间需要 12 分钟。

同学写了一篇

错误一:作为对比测试,测试数组应该为同一个,否则测试数据没有可比性

错误二:对比组中对List的使用不对,List默认创建的数组大小为4,每次增长为4,那么这里就会反复重新创建新的数组次数为log10000000次左右当然会比Linq慢很多

错误三:面对Linq接近0毫秒的处理能力,稍微有点经验的同学就知道这是不可能的,除非是很强很强的计算机,至于为什么后面给出答案,总之linq查询里肯定有猫腻,直接调用tolist()强制返回结果再说;//这里Stone W在评论中对ToList有质疑,我之所以ToList是为了和第二组进行对比,因为第二组得到的结果是一个List,我很奇怪,这次的对比测试到底是为了测试得到两个结果集的算法对比呢还是测试Count算法的对比呢?如果是前者,一个拿到的是IEnumerable的对象一个是List对象,牛跟闹钟怎么对比哪个跑的快呢?也只有在调用ToList的时候才会真正执行Linq的算法也就是下面的嵌套类WhereListIterator;当然如果是为了进行Count对比的话那么对比组二中的算法真的有点拙劣,我想不会有谁会用方法二来统计。

下面是修改了如上三个明显错误后的代码,如果哪位同学有补充欢迎留言:

[Fact]        public void LinqTest()        {            TestLinq(1);            TestLinq(2);            TestLinq(3);        }        public void TestLinq(int time)        {            const int listCount = 10000000; // 数组长度            Random random = new Random(); // 数据随机构建值            // 数组构建             List
list1 = new List
(); for (int i = 0; i < listCount; i++) { list1.Add(random.Next(10000)); } // 效率测试内容:提取数组中数值大于的100的数组 // LINQ 测试 Stopwatch linq_Stopwatch = new Stopwatch(); linq_Stopwatch.Start(); var linqList = (from num in list1 where num > 100 select num).ToList(); linq_Stopwatch.Stop(); // 普通方式 测试 Stopwatch before_Stopwatch = new Stopwatch(); before_Stopwatch.Start(); List
beforeList = new List
(10000000); for (int i = 0; i < list1.Count(); i++) { if (list1[i] > 100) beforeList.Add(list1[i]); } before_Stopwatch.Stop(); Console.WriteLine( String.Format("第{0}次测试,测试:{5}条数据。\n\r \t LINQ用时:{1}毫秒,筛选了{2}条数据。\n\r\t 普通用时:{3}毫秒,筛选了{4}条数据。\r\n", time, linq_Stopwatch.ElapsedMilliseconds, linqList.Count(), before_Stopwatch.ElapsedMilliseconds, beforeList.Count(), listCount)); }

测试结果:

第1次测试,测试:10000000条数据。

LINQ用时:448毫秒,筛选了9898832条数据。
普通用时:437毫秒,筛选了9898832条数据。

第2次测试,测试:10000000条数据。
LINQ用时:516毫秒,筛选了9899569条数据。
普通用时:460毫秒,筛选了9899569条数据。

第3次测试,测试:10000000条数据。
LINQ用时:608毫秒,筛选了9899231条数据。
普通用时:470毫秒,筛选了9899231条数据。

 

结论:Linq在实现灵活性提高编写效率的时候牺牲了一定的性能,当然这个是必须的,有的必有失嘛。

我的选择:绝大部分时候使用Linq,在对性能要求高的时候使用普通的迭代;

 

 0毫秒的秘密:

var linqList = (from num in list1 where num > 100 select num)

先看看这个LinqList的类型(Console.WriteLine(linqList.GetType().FullName);):System.Linq.Enumerable+WhereListIterator`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

可以看到这是一个嵌套类,作用是对Where 条件进行迭代操作,贴上它的源代码:

class WhereListIterator
: Iterator
{ List
source; Func
predicate; List
.Enumerator enumerator; public WhereListIterator(List
source, Func
predicate) { this.source = source; this.predicate = predicate; } public override Iterator
Clone() { return new WhereListIterator
(source, predicate); } public override bool MoveNext() { switch (state) { case 1: enumerator = source.GetEnumerator(); state = 2; goto case 2; case 2: while (enumerator.MoveNext()) { TSource item = enumerator.Current; if (predicate(item)) { current = item; return true; } } Dispose(); break; } return false; } public override IEnumerable
Select
(Func
selector) { return new WhereSelectListIterator
(source, predicate, selector); } public override IEnumerable
Where(Func
predicate) { return new WhereListIterator
(source, CombinePredicates(this.predicate, predicate)); } }

真相大白于天下。   

ps:下面是原文代码的截图

 

 

 

转载地址:http://dugpa.baihongyu.com/

你可能感兴趣的文章
关于redis的几件小事(六)redis的持久化
查看>>
package.json
查看>>
webpack4+babel7+eslint+editorconfig+react-hot-loader 搭建react开发环境
查看>>
Maven 插件
查看>>
初探Angular6.x---进入用户编辑模块
查看>>
计算机基础知识复习
查看>>
【前端词典】实现 Canvas 下雪背景引发的性能思考
查看>>
大佬是怎么思考设计MySQL优化方案的?
查看>>
<三体> 给岁月以文明, 给时光以生命
查看>>
Android开发 - 掌握ConstraintLayout(九)分组(Group)
查看>>
springboot+logback日志异步数据库
查看>>
Typescript教程之函数
查看>>
Android 高效安全加载图片
查看>>
vue中数组变动不被监测问题
查看>>
3.31
查看>>
类对象定义 二
查看>>
收费视频网站Netflix:用户到底想要“点”什么?
查看>>
MacOS High Sierra 12 13系统转dmg格式
查看>>
关于再次查看已做的多选题状态逻辑问题
查看>>
动态下拉菜单,非hover
查看>>