.NET 4.0 中的 Array.Sort() 发生了什么? TrySZSort() 消失了吗?

发布于 2025-01-07 09:24:16 字数 2181 浏览 0 评论 0原文

我想知道为什么下面的代码片段没有给出预期的结果?它对一个不太小的随机数组进行排序,并使用 3 种不同的方法。我期望的速度是这样的:

  1. Array.Sort() - 最快通过使用本机 TrySZSort 函数,正如我从 .NET 2.0 中回忆的那样
  2. 通过使用自定义比较器类进行降序排序
  3. 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. ...

所以,lambda 确实是最慢的。但为什么普通的升序 Array.Sort 不再更快了呢?是因为 Array.Sort(T[], Comparer) 已得到改进,还是 TrySZSort 只是被删除了?或者我错过了什么?

(发布版本,没有调试,现在没有可用的反射器;))谢谢!

更新: 根据@Reed Copsey 的提示,lambda 表达式是不公平的。我尝试将其更改为与比较器相同的值。速度加快了。 Asc/lambda 从 55% -> 55% 75%。所以它仍然慢得多。

I wonder why the following snippet does not give the expected result? It sorts a not too small random array and uses 3 different methods for it. I was expecting the speed to come out as so:

  1. Array.Sort() - fastest by using the native TrySZSort function as I recall from .NET 2.0
  2. Descending sort by using the custom Comparer class
  3. The lambda expression sort.

The Code:

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(); 
}

But strangely, it gives the following:

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. ...

So, the lambda really is slowest. But how comes, the plain ascending Array.Sort is not faster anymore? Is it, because Array.Sort(T[], Comparer) has been improved or has TrySZSort simply been removed? Or did I miss something?

(Release build, no Debug, no Reflector available right now ;) ) Thanks!

UPDATE:
According to the hint by @Reed Copsey, the lambda expression is not fair. I tried to change it to the same as the comparer does. The speed went up. Asc / lambda went from 55% -> 75%. So it still is considerably slower.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

素罗衫 2025-01-14 09:24:16

所以,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

当您运行这些计时时,您是否附加了视觉工作室主机?如果您在 VS 中运行(即:默认情况下使用 F5 而不是 Ctrl+F5),即使是发布版本也会显着变慢。


另请注意,就 lambda 而言,您的测试并不完全公平。您应该使用相同的测试机制,即:

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

So, the lambda really is slowest. But how comes, the plain ascending Array.Sort is not faster anymore? Is it, because Array.Sort(T[], Comparer) has been improved or has TrySZSort simply been removed? Or did I miss something?

Well, there's two issues here. First, this really depends on your build and system -

On my system, in x64, Array.Sort() is the fastest, by a significant amount:

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

On x86, things are slightly different - but not nearly the same significance as you're showing:

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

Did you have the visual studio host attached when you ran these timings? Even a release build will be dramatically slower if you run within VS (ie: F5 instead of Ctrl+F5 by default).


Also note that your test isn't completely fair, in regards to the lambda. You should use the same mechanism for testing, which would be:

Array.Sort<double>(a, (x, y) => (x > y) ? -1 : 1);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文