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。”

posted @ 2013-01-29 10:02  脸谱匠  阅读(18169)  评论(13编辑  收藏  举报