2012-02-20 205 views
5

我想知道爲什麼下面的代碼片段沒有給出預期的結果?它對一個不太小的隨機數組進行排序,並使用3種不同的方法。我期待的速度出來像這樣:.NET 4.0中的Array.Sort()發生了什麼? TrySZSort()消失了嗎?

  1. 的Array.Sort() - 最快通過使用本地TrySZSort功能我從.NET 2.0
  2. 記得使用自定義比較器類
  3. 降序排序
  4. lambda表達式排序。

驗證碼:

class DescComparer : IComparer<double> { 
    // simple comparison 
    // (yes, its not exactly correct ...) 
    public int Compare(double x, double y) { 
     return (x > y) ? -1 : 1; 
    } 
} 
static void Main(string[] args) { 
    Stopwatch sw = new Stopwatch(); 
    Random rand = new Random(); 
    DescComparer comparer = new DescComparer(); 
    double[] a = new double[1000000]; 
    for (int r = 0; r < 20; r++) { 

     // init array 
     for (int i = 0; i < a.Length; i++) a[i] = rand.NextDouble(); 
     sw.Restart(); 
     Array.Sort(a); 
     sw.Stop(); 
     Console.WriteLine("ascending took: {0} ms ", sw.ElapsedMilliseconds); 

     // init array 
     for (int i = 0; i < a.Length; i++) a[i] = rand.NextDouble(); 
     sw.Restart(); 
     Array.Sort<double>(a, comparer); 
     sw.Stop(); 
     Console.WriteLine("descending took: {0} ms ", sw.ElapsedMilliseconds); 

     // init array 
     for (int i = 0; i < a.Length; i++) a[i] = rand.NextDouble(); 
     sw.Restart(); 
     Array.Sort<double>(a, (x,y) => -x.CompareTo(y)); 
     sw.Stop(); 
     Console.WriteLine("desc lambda took: {0} ms ", sw.ElapsedMilliseconds); 

    } 
    Console.Read(); 
} 

但奇怪的是,它提供了以下:

ascending took: 514 ms 
descending took: 537 ms 
desc lambda took: 915 ms 
ascending took: 511 ms 
descending took: 492 ms 
desc lambda took: 923 ms 
ascending took: 511 ms 
descending took: 483 ms 
desc lambda took: 912 ms 
ascending took: 511 ms 
descending took: 485 ms 
desc lambda took: 914 ms 
ascending took: 518 ms 
descending took: 485 ms 
desc lambda took: 924 ms 
... a.s.o. ... 

因此,拉姆達真的是最慢的。但是,怎麼樣,平原上升Array.Sort不再更快?是否,因爲Array.Sort(T [],Comparer)已被改進或TrySZSort被簡單地刪除?或者我錯過了什麼?

(發佈版本,沒有調試,目前沒有Reflector可用;))謝謝!

更新: 根據@Reed Copsey的提示,lambda表達式不公平。我試圖改變它與比較器相同。速度提高了。 Asc/lambda從55% - > 75%。所以它仍然相當慢。

+1

我無法解釋的性能結果,但看着反射,TrySZSort就不走了,並呼籲雙方'Sort'和'排序'方法,但只有當比較器爲空或默認時。 – 2012-02-20 18:46:23

+0

@ Meta-Knight hm。有趣!所以看起來,管理方略微增加了一些。感謝您告訴! – 2012-02-20 18:53:03

+1

是的,Array.Sort()在.NET 4中被重寫。有幾種分類器。當比較器出現故障時,你可能會得到一個不會陷入無限循環的環路。通過查看參考源中提供的註釋源代碼來追查它。 – 2012-02-20 19:32:15

回答

5

所以,lambda確實是最慢的。但是,怎麼樣,平原上升Array.Sort不再更快?是否,因爲Array.Sort(T [],Comparer)已被改進或TrySZSort被簡單地刪除?或者我錯過了什麼?

嗯,這裏有兩個問題。首先,這真的取決於你的構建和系統 -

在我的系統,在x64上,Array.Sort()最快,由顯著量:

ascending took: 192 ms 
descending took: 248 ms 
desc lambda took: 326 ms 
ascending took: 194 ms 
descending took: 247 ms 
desc lambda took: 326 ms 

在x86上,事情稍有不同 - 但幾乎沒有相同的意義,因爲你正在展示:

ascending took: 235 ms 
descending took: 223 ms 
desc lambda took: 325 ms 
ascending took: 234 ms 
descending took: 222 ms 
desc lambda took: 325 ms 

你有當您運行這些時間附着在Visual Studio主機?如果您在VS中運行,即使發佈版本也會顯着變慢(例如,默認情況下,F5代替Ctrl + F5)。


另外請注意,您的測試是不完全公平的,關於拉姆達。您應該使用的測試相同的機制,具體做法是:

Array.Sort<double>(a, (x, y) => (x > y) ? -1 : 1); 
+0

正確。與lambda(X86)的區別不太重要。但沒有拉姆達的速度比asc/desc大致相同:5%。 – 2012-02-20 19:00:57