c# 测试篇之Linq性能测试
以下测试结果有误!!!
linq为延迟执行语句,调用结果时,才执行查询语句。
留文自省!!
.Net 3.5之后出现了linq,它包含几个分类:LINQ to Object, LINQ to XML, LINQ to SQL, LINQ to DataSet,LINQ to ADO.NET。本篇说说linq to object的部分用法的性能测试。
首先,用linq实现修改集合中的每个元素。
List<string> xxx = new List<string>() { "aaaa", "bbbb", "aaabbb", "cccc", "aaaccc" }; var linq = xxx.Select(x => "000" + x);
值得注意的是,Select返回的类型是IEnumerable的,可就是可枚举类型。它的优势在于多个linq语句一起执行时,只会历遍一次(尽量少的次数)来获取结果。
如果上面的这段代码用基本的c#语句来实现,代码应该如下:
var yyy = new List<string>(); foreach (var item in xxx) yyy.Add("000" + item);
下面通过代码来同时测试两者的性能。
List<string> xxx = new List<string>() { "aaaa", "bbbb", "aaabbb", "cccc", "aaaccc" }; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch watch2 = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch watch3 = new System.Diagnostics.Stopwatch(); watch.Start(); for (int i = 0; i < 100000; i++) { var linq = xxx.Select(x => "000" + x);//Linq,返回IEnumerable } watch.Stop(); var useTime = (double)watch.ElapsedMilliseconds; watch2.Start(); for (int i = 0; i < 100000; i++) { var linq = xxx.Select(x => "000" + x).ToList();//Linq + ToList,返回List } watch2.Stop(); var useTime2 = (double)watch2.ElapsedMilliseconds; watch3.Start(); for (int i = 0; i < 100000; i++) { var yyy = new List<string>(); foreach (var item in xxx) yyy.Add("000" + item);//foreach,返回List } watch3.Stop(); var useTime3 = (double)watch3.ElapsedMilliseconds;
用十万次的循环来测试消耗的时间。测试对象包括:
纯Linq语句的修改,返回IEnumerable<string>;Linq语句修改 + ToList(),最后返回List<string>;foreach历遍修改,返回List<string>。执行这段代码,查看useTime的结果。运行一次的结果如下:
useTime = 11.0
useTime2 = 87.0
useTime3 = 73.0
由这个结果可以得出:Linq修改的速度最快,其次是foreach历遍,linq+ToList最慢。在平时的使用过程中,如果返回的结果不是必须转换成List集合的情况下,用Linq可以更快更节省代码!不熟悉IEnumerable接口的可以深入了解一下,它是可枚举类型,可以用foreach来历遍,List和Array都继承了这个接口。
linq的另一个很明显的优势是,它可以多个函数命令累积执行。形如Linq.Select().Where().GroupBy().Select();这样的代码无疑更精简。以下同样通过代码来测试这样的linq效率如何。
实现的目标:在修改的同时查询过滤,同时用linq和foreach历遍实现。
List<string> xxx = new List<string>() { "aaaa", "bbbb", "aaabbb", "cccc", "aaaccc" }; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); for (int i = 0; i < 100000; i++) { var linq = xxx.Select(x => "000" + x).Where(x => x.IndexOf("aaa") != -1).ToList(); } watch.Stop(); var useTime = (double)watch.ElapsedMilliseconds; System.Diagnostics.Stopwatch watch2 = new System.Diagnostics.Stopwatch(); watch2.Start(); for (int i = 0; i < 100000; i++) { var yyy = new List<string>(); foreach (var item in xxx) { var tmp = "000" + item; if (tmp.IndexOf("aaa") != -1) yyy.Add(tmp); } } watch2.Stop(); var useTime2 = (double)watch2.ElapsedMilliseconds;
执行的结果:useTime = 18.0; useTime2 = 379.0 效率差距出来了。
在只有单个命令的前提下,linq和foreach执行的效率相差只有几倍,多个命令时,linq的效率就明显比foreach快很多了。
补充:在linq语句的后面加上ToList()来执行linq语句。最终结果:useTime = 404.0; useTime2 = 333.0.
补充测试:select+groupby+select VS foreach
List<KeyValuePair<string, string>> xxx = new List<KeyValuePair<string, string>>() { new KeyValuePair<string,string>("a", "b"), new KeyValuePair<string,string>("a", "c"), new KeyValuePair<string,string>("a", "d"), new KeyValuePair<string,string>("a", "e"), new KeyValuePair<string,string>("b", "a"), new KeyValuePair<string,string>("b", "b"), new KeyValuePair<string,string>("b", "c") }; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); List<string> res = new List<string>(); for (int i = 0; i < 100000; i++) { res.Clear(); var linq = xxx.Select(x => new { x.Key, Value = "000" + x.Value }) .GroupBy(x => x.Key) .Select(x => x.Key + ":" + x.Select(y => y.Value).Aggregate((y, z) => y + "_" + z)); res.AddRange(linq); } watch.Stop(); var useTime = (double)watch.ElapsedMilliseconds; System.Diagnostics.Stopwatch watch2 = new System.Diagnostics.Stopwatch(); watch2.Start(); for (int i = 0; i < 100000; i++) { res.Clear(); var dic = new Dictionary<string, string>(); foreach (var x in xxx) { var tmp = "_" + "000" + x.Value; if (!dic.ContainsKey(x.Key)) dic.Add(x.Key, tmp); else dic[x.Key] += tmp; } foreach (var x in dic) res.Add(x.Key + ":" + (string.IsNullOrWhiteSpace(x.Value) ? "" : x.Value.Remove(0, 1))); } watch2.Stop(); var useTime2 = (double)watch2.ElapsedMilliseconds;
调试得到结果:useTime = 422.0; useTime2 = 228.0。结合上面的调试结果,linq的执行效率基本上都要比用基础代码编写的foreach要慢一点。
转载请注明出处:http://www.cnblogs.com/icyJ/
补充二:其他人的说法。没有测试过。AsParallel()这个方法值得深究。
“要真正比较linq的好处,不能用这么简单的代码的。你尝试一下
int[] result=list.AsParallel().Where(i=>i%3==0).Select(i=>i*i).ToArray();
然后用for循环和lambda同样实现一个多线程的求解,你就知道linq的威力了。
一般来说,如果你自己调度的不好,性能肯定比linq差。但是如果你调度的好,你会发现“我写了这么多代码,只比linq快了那么一点点,但是linq只有一行”,所以最终你会选择linq。”