簡體   English   中英

字典中的前100個值 <string, int> -為什么LinQ比foreach循環快得多

[英]Top 100 values in a Dictionary<string, int> - Why is LinQ so much faster than a foreach loop

我正在編寫一個簡單的應用程序,以分析巨大的textfile(60gb)並存儲所有單詞以及它出現在文件中的時間。 為了測試起見,我將文件切成2gb。

我發現字典中的單詞和計數雖然很難相信我所看到的結果。

詞典中的單詞總數:1128495

我正在使用的代碼:

sw.Start();

StringBuilder sb = new StringBuilder();
sb.AppendFormat("<html><head></head><body>");
lock (Container.values)
{
    int i = int.Parse(ctx.Request.QueryString["type"]);
    switch (i)
    {
        case 1: //LinQ
            var values = Container.values.OrderByDescending(a => a.Value.Count).Take(100);
            foreach (var value in values)
            {
                sb.AppendFormat("{0} - {1}<br />", value.Key, value.Value.Count);
            }
            break;
        case 2: //Foreach
            foreach (var y in Container.values)
            {

            }
            break;
        case 3: //For
            for (int x = 0; x < Container.values.Count; x++)
            {

            }
            break;
    }                
}
sw.Stop();
sb.AppendFormat("<br /><br /> {0}", sw.ElapsedMilliseconds);
sb.AppendFormat("</body>");

跑兩次,下面的速度以毫秒為單位:

LinQ:#1:598,#2 609

Foreach:#1 1000,#1020

為什么LinQ比foreach更快? 我認為LinQ必須循環遍歷Dictionary本身,因此它如何進行+如此及時地將其排序?

編輯:編譯為發布模式后,結果如下:LinQ:796(較慢?)foreach:945

該應用程序是一個簡單的控制台應用程序,代碼在HttpListener中執行

編輯2:我設法弄清楚了問題所在。 當我初始化字典時,我將其容量設置為89000000(在處理60gb文件時,否則將拋出OutOfMemory異常)。 由於某種原因,這會大大降低foreach循環的性能。 如果將容量設置為1128495,則foreach循環將在56毫秒內執行。

為什么會這樣呢? 如果將計數器放在循環中,即使容量為89000000,它也只能運行1128495次。

編譯器通過調用GetEnumerator(),然后在枚舉器上重復調用MoveNext和Current,來實現foreach循環。 LINQ的OrderByDescending通常以完全相同的方式工作,它基本上進行了foreach提取所有元素,然后對其進行排序。

快速瀏覽ILSpy可以發現,OrderByDescending將容器放入名為Buffer<T>的內部類型中,該類型具有優化:如果容器實現ICollection<T> ,則它使用ICollection<T>.CopyTo而不是foreach循環。 通常,OrderByDescending仍不會比foreach循環快,因為提取元素后必須對其進行排序。

您是否在foreach循環中遺漏了可能解釋其速度較慢的代碼? 如果您確實使用了空的foreach循環,則可能是由於Container.valuesIEnumerator<T>類型(或GetEnumerator方法)與其CopyTo方法相比速度較慢。

您的LINQ版本僅需要前100個元素!

刪除.Take(100)以便進行比較!

暫無
暫無

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

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