【发布时间】:2012-07-11 12:04:45
【问题描述】:
结果
使用一千万个随机ints 的列表(每次相同的种子,平均重复 10 次):
listCopy.Sort(Comparer<int>.Default) 需要 314 毫秒。
使用
sealed class IntComparer : IComparer<int>
{
public int Compare(int x, int y)
{
return x < y ? -1 : (x == y ? 0 : 1);
}
}
listCopy.Sort(new IntComparer()) 需要 716 毫秒。
一些变化:
- 使用
struct IntComparer代替sealed class:771 毫秒 - 使用
public int Compare(int x, int y) { return x.CompareTo(y); }:809ms
评论
Comparer<int>.Default 返回一个GenericComparer<int>。根据 dotPeek,我们有:
internal class GenericComparer<T> : Comparer<T> where T : IComparable<T>
{
public override int Compare(T x, T y)
{
if ((object) x != null)
{
if ((object) y != null)
return x.CompareTo(y);
else
return 1;
}
else
return (object) y != null ? -1 : 0;
}
...
}
显然,这不应该比我使用CompareTo 的IntComparer 变体更快。
我没有在ArraySortHelper<T> 中找到任何相关内容,这似乎是List<T>.Sort 的核心。
我只能猜测 JIT 在这里做了一些神奇的特殊情况(将使用 Comparer<int>.Default 的排序替换为不执行任何 IComparer<T>.Compare 调用的专用排序实现,或类似的东西)?
编辑:上面的时间太低了 5.9214729782462845 (Stopwatch 和 TimeSpan 对“滴答声”有不同的定义)。不过不影响重点。
【问题讨论】:
-
我们能看到表明您实际计时的代码吗?很多“为什么 X 比 Y 快?”问题一开始就存在时间问题。
-
另外,如果您将 IntComparer 更改为返回
x - y,这对运行时有何影响? -
尝试以不同的顺序运行它们,看看是否得到相同的结果
-
@FunctorSalad 你为什么要做
GC.Collect? GC.Collect 不是同步的,除非用GC.WaitForPendingFinalizers调用。如果您不等待终结器,则收集可能仍在您的定时代码的后台进行。 -
@Cameron 返回 x - y 不是一个好主意。你很容易遇到过低的问题;考虑 x = int.MinValue 和 y = int.MaxValue。你最终会返回一个正值而不是一个负值。
标签: c# performance sorting