zoukankan      html  css  js  c++  java
  • 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。”

  • 相关阅读:
    JSP第二次作业
    软件测试课堂练习
    内容提供者读取短信信息
    购物车
    第六周jsp
    第四周jsp
    第一周 软件测试
    第八次安卓
    安卓第七次作业
    安卓第六次作业
  • 原文地址:https://www.cnblogs.com/icyJ/p/linq.html
Copyright © 2011-2022 走看看