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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM