2012-02-20 204 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