簡體   English   中英

為什么LINQ操作比正常循環更快?

[英]Why can LINQ operations be faster than a normal loop?

在今天的編程討論中,我和朋友有點困惑。 作為一個例子,我們創建了一個虛構的問題,即具有n個隨機整數的List<int> (通常為1.000.000),並且想要創建一個函數,該函數返回有多個整數的集合。 很簡單的東西。 我們創建了一個LINQ語句來解決這個問題,以及一個基於普通插入排序的算法。

現在,當我們測試代碼運行的速度時(使用System.Diagnostics.StopWatch ),結果令人困惑。 LINQ代碼不僅優於簡單排序,而且運行速度比單個 foreachfor因為它只執行了一個循環的列表,並且沒有內部操作(在側軌上,我認為編譯器是應該發現並完全刪除)。

如果我們在程序的同一執行中生成一個新的List<int>隨機數並再次運行LINQ代碼,性能將增加幾個數量級(通常為千倍)。 空循環的性能當然是相同的。

那么,這里發生了什么? LINQ使用並行性是否優於正常循環? 這些結果怎么可能呢? LINQ使用以n * log(n)運行的quicksort,其定義已經慢於n。

第二輪的性能飛躍發生了什么?

我們對這些結果感到困惑和興趣,並希望從社區中獲得一些澄清的見解,只是為了滿足我們自己的好奇心。

毫無疑問,你實際上沒有執行過查詢,你只是定義了它。 LINQ構造一個表達式樹,在您執行需要迭代枚舉的操作之前,該表達式樹不會被實際評估。 嘗試將ToList()Count()操作添加到LINQ查詢以強制評估查詢。

根據您的評論,我希望這與您所做的類似。 注意:我沒有花時間搞清楚查詢是否盡可能高效; 我只想要一些查詢來說明代碼的結構。

var dataset = ...

var watch = Stopwatch.StartNew();

var query = dataset.Where( d => dataset.Count( i => i == d ) > 1 );

watch.Stop();  // timer stops here

foreach (var item in query) // query is actually evaluated here
{
   ... print out the item...
}

我建議當你的算法不完美時(或者你的代碼中有問題),LINQ只比'正常循環'快。 因此,如果你沒有編寫有效的排序算法等,LINQ的排序速度會比你快。

LINQ通常與正常循環的速度“一樣快”或“足夠接近”,並且可以更快(更簡單)地進行編碼/調試/讀取。 這是它的好處 - 而不是執行速度。

如果它的執行速度比空循環快,那么你做錯了。 最有可能的是,正如評論中所建議的那樣,您不會考慮延遲執行,並且LINQ語句實際上並未執行。

如果您沒有啟用“優化代碼”編譯,您可能會看到此行為。 (這肯定會解釋為什么沒有刪除空循環。)

然而,LINQ底層代碼是已編譯代碼的一部分,它肯定已經過優化(由JIT, NGen或類似代碼)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM