数组排序方法的性能比较(1):注意事项及试验

昨天有朋友写了一篇文章,其中比较了List<T>的Sort方法与LINQ中排序方法的性能,而最终得 到的结果是“LINQ排序方法性能高于 List<T>.Sort方法”。这个结果不禁让我很疑惑。因为 List<T>.Sort方法是改变容器内部元素的顺序,而 LINQ排序后得到的是一个新的序列。假如两个 排序方法的算法完全一致,LINQ排序也比对方多出元素复制的开销,为什么性能反而会高?如果LINQ排序 的算法/实现更为优秀,那为什么.NET Fx不将List<T>.Sort也一并优化一下呢?于是今天我也对这 个问题进行了简单的试验。

注意事项

在后面的评论中有人说,List<T>.Sort是“内部排序”,而LINQ排序是“外部排序”。但是根 据外部排序的定义,这个说法是不正确的。“外部排序”是指在排序目标规模太大,导致主存相对太小( 如内存)而不够放,不得不利用外部存储(如硬盘)做一些“过渡”的排序方式。因此,LINQ排序虽然生 成了新的序列,但还是内部排序。事实上,从定义中我们也可以很容易推断出,如果数据规模相同,外部 排序的性能一般总是比内部排序要差——不过事实上我们不太好做这样的比较,因为如果是能够进行内部 排序的情况下,谁会利用麻烦的外部排序呢?

那篇文章中得到的结果是不对的,那么问题究竟出在什么地方呢?在我看来,问题主要出在以下两点 。

首先,原文作者使用了ASP.NET作为测试环境。值得注意的是,ASP.NET执行.NET代码的时候,使用的 是IIS进程中托管的CLR,它的配置和直接运行.NET应用程序时不同(不同的CLR托管方式配置很可能不一 样——例如SQL Server里托管的CLR)。例如,ASP.NET中每个线程的调用栈为250K,而直接运行.NET应用 程序时这个大小为1M。根据我的经验(也就是说我无法确切地“证明”这个说法),在ASP.NET中执行此 类性能测试得到的结果可能很不稳定。因此,一般我建议使用一个最普通的Console应用程序来进行性能 测试。

其次,也是更重要的原因,便是原作者只测试了一次排序的性能。这是性能测试中的大忌讳,因为这 么做的话误差实在太大。例如,会不会在进行某一个方法的测试时,忽然系统起了一个后台进程进行维护 ,动用了一部分CPU和内存资源,从而导致测试消耗的时间很冤枉地增加。而且,.NET程序是有一个“预 热”过程的,这导致代码在第一次执行时需要有一个生成本机代码的过程(俗称“预热”)。这个过程和 代码的执行效率是无关的,因为它无论如何只会产生一次消耗,而代码是会被执行无数次的。因此,在进 行测试的时候,一定要将测试目标反复执行N次,至少要让执行耗时到达“秒”级别,这样的结果才有一 定参考价值。如果执行时间太少的话测试也可能不准确——要知道“计时器”也是有开销,也是有误差的 ,我们要得到尽量准确的结果。

最后,我强烈建议使用CodeTimer进行计时,因为在它的Initialize方法中会将当前进程及线程的优先 级设置到最高,以此减少其他无关因素所造成的干扰。如果可以的话,其实也应该尽量关闭系统中其他应 用程序或服务,并且最好可以断开网络(也是一个道理)。当然Release编译也是一定需要的。而且,如 果您一定需要使用ASP.NET 进行性能测试的话,也千万记得要在web.config中将<compilation /> 节点的debug属性设为false——考虑到原作者忽略了之前犯了很明显的忌讳,我强烈怀疑这点也没有满足 。:)

因此,我认为那篇文章中的测试结果是不准确的,参考价值很低。

时间: 2025-01-26 14:37:09

数组排序方法的性能比较(1):注意事项及试验的相关文章

数组排序方法的性能比较(上):注意事项及试验

昨天有朋友写了一篇文章,其中比较了List的Sort方法与LINQ中排序方法的性能,而最终得到的结果是"LINQ排序方法性能高于List.Sort方法".这个结果不禁让我很疑惑.因为List.Sort方法是改变容器内部元素的顺序,而LINQ排序后得到的是一个新的序列.假如两个排序方法的算法完全一致,LINQ排序也比对方多出元素复制的开销,为什么性能反而会高?如果LINQ排序的算法/实现更为优秀,那为什么.NET Fx不将List.Sort也一并优化一下呢?于是今天我也对这个问题进行了简

艾伟_转载:数组排序方法的性能比较(上):注意事项及试验

昨天有朋友写了一篇文章,其中比较了List的Sort方法与LINQ中排序方法的性能,而最终得到的结果是"LINQ排序方法性能高于List.Sort方法".这个结果不禁让我很疑惑.因为List.Sort方法是改变容器内部元素的顺序,而LINQ排序后得到的是一个新的序列.假如两个排序方法的算法完全一致,LINQ排序也比对方多出元素复制的开销,为什么性能反而会高?如果LINQ排序的算法/实现更为优秀,那为什么.NET Fx不将List.Sort也一并优化一下呢?于是今天我也对这个问题进行了简

数组排序方法的性能比较(中):Array.Sort 实现分析

昨天我们比较了Array.Sort方法与LINQ排序的性能,知道了LINQ排序的性能以较大幅度落后于Array.Sort方法.而对于Array.Sort来说,性能最高的是其中使用Comparer.Default作为比较器的重载方法.在前文的末尾我们做出了推测:由于排序算法已经近乎一个标准了(快速排序),因此从算法角度来说,Array.Sort方法和LINQ排序上不应该有那么大的差距,因此造成两者性能差异的原因,应该是具体实现方式上的问题. 下载.NET框架的代码 既然是比较实现的区别,那么阅读代

一起谈.NET技术,数组排序方法的性能比较(中):Array.Sort&lt;T&gt; 实现分析

昨天我们比较了Array.Sort方法与LINQ排序的性能,知道了LINQ排序的性能以较大幅度落后于Array.Sort方法.而对于Array.Sort来说,性能最高的是其中使用Comparer.Default作为比较器的重载方法.在前文的末尾我们做出了推测:由于排序算法已经近乎一个标准了(快速排序),因此从算法角度来说,Array.Sort方法和LINQ排序上不应该有那么大的差距,因此造成两者性能差异的原因,应该是具体实现方式上的问题. 下载.NET框架的代码 既然是比较实现的区别,那么阅读代

艾伟_转载:数组排序方法的性能比较(中):Array.Sort&lt;T&gt; 实现分析

昨天我们比较了Array.Sort方法与LINQ排序的性能,知道了LINQ排序的性能以较大幅度落后于Array.Sort方法.而对于Array.Sort来说,性能最高的是其中使用Comparer.Default作为比较器的重载方法.在前文的末尾我们做出了推测:由于排序算法已经近乎一个标准了(快速排序),因此从算法角度来说,Array.Sort方法和LINQ排序上不应该有那么大的差距,因此造成两者性能差异的原因,应该是具体实现方式上的问题. 下载.NET框架的代码 既然是比较实现的区别,那么阅读代

一起谈.NET技术,数组排序方法的性能比较(3):LINQ排序实现分析

上次我们分析了Array.Sort方法的实现方式,并了解到类库会为一些特例而使用高性能的排序方式--int数组便是这样一例,因此从测试结果上来看其性能特别高.不过从数据上看,即便是在普通的情况下,Array.Sort的性能也比LINQ排序要高.不过也有朋友从测试中得出的结论正好相反,这又是为什么呢?那么现在,我们再来分析一下LINQ排序的实现方式吧,希望这样可以了解到两者性能差别的秘密. 只可惜,LINQ排序的代码在System.Core.dll程序集中,微软没有发布这部分源代码,我们只得使用.

数组排序方法的性能比较(5):对象大小与排序性能

在我公开测试结果之后,有朋友也进行了其他测试.在测试中我使用的是int数组,经过分析之后我们 了解到Array.Sort<T>对于int数组有特殊的优化.于是,某些朋友使用了一些引用类型的数组进行 排序,得到Array.Sort<T>方法的性能落后于LINQ排序--虽然由于测试方式的问题,这个结果和 结论都不太妥当.不过在讨论的过程中,我们都意识到了一个问题:在其他条件不变的情况下,引用类型 的字段越多,Array.Sort<T>方法所需时间就越久.这次我们就来讨论一下

数组排序方法的性能比较(4):LINQ方式的Array排序

经过前两篇文章的分析,我们已经了解了Array.Sort<T>与LINQ排序两种实现方式的差别:前者 直接比较两个元素的大小,而后者先选出每个元素的"排序依据"再进行比较.因此,虽然后者需要相对 较多的"周边工作",但由于每次比较时都可以仅仅使用高效的基础类型(如int),因此从整体来看, 两者的性能高低难以辨别.不过,既然我们已经了解LINQ排序"高效"的原因,又能否将其利用在数组排 序上呢?程序是人写的,此类问题大都有肯定的答案.

数组排序方法的性能比较(3):LINQ排序实现分析

上次我们分析了Array.Sort<T>方法的实现方式,并了解到类库会为一些特例而使用高性能的排 序方式--int数组便是这样一例,因此从测试结果上来看其性能特别高.不过从数据上看,即便是在普 通的情况下,Array.Sort<T>的性能也比LINQ排序要高.不过也有朋友从测试中得出的结论正好相 反,这又是为什么呢?那么现在,我们再来分析一下LINQ排序的实现方式吧,希望这样可以了解到两者性 能差别的秘密. 只可惜,LINQ排序的代码在System.Core.dll程序集中,微软没