这是随机整数的枚举:
var r = new Random();
var e = Enumerable.Repeat(1, 10_000_000).Select( _ => r.Next());
您认为哪个版本更快?
var result = e.OrderBy(x => x).Last(); //materialize the IEnumerable
或
var l = e.ToList();
l.Sort();
var result = l.Last();
我希望第一个示例中的.OrderBy(x => x).Last()
是
优化后仅对列表的一小部分进行排序或仅对列表进行O(n)遍历。
扰流器: 不是。
但是,这两个版本的性能至少应该差不多,对吗?我的意思是:
在第一个中,OrderBy()
分配一个临时数组并将其排序。
在第二个中,我显式分配了一个列表并将其Sort()
保留在适当的位置。
实际结果表明,OrderBy()
示例的速度慢了4-5倍! (5-6秒和1.2-1.3秒)
任何人都可以提出原因的解释吗?
.OrderBy(x => x)
情况确实为每个元素执行其x => x
身份lambda。
之间的区别:
var result2 = e.Last();
和
var result2 = e.Select(x=>x).Last();
是可测量的,但很小:在第二种情况下多了30-50 ms。因此,这并不能解释巨大的差距。
答案 0 :(得分:3)
似乎List
有一个special optimized C++ version of sorting,用于比较类型与Comparer.Default
或没有IComparer
的类型。 OrderBy
总是进行适用于任何类型和IComparer
的通用排序。
如果将Select
结果替换为MyInt
类型的对象,如下所示:
public class MyInt : IComparable {
public int value;
public MyInt(int newv) => value = newv;
public int CompareTo(object obj) {
if (obj is MyInt m2) {
return value.CompareTo(m2.value);
}
else if (obj is int i2) {
return value.CompareTo(i2);
}
else {
throw new Exception($"can't compare MyInt to {obj.GetType()}");
}
}
}
var e = Enumerable.Repeat(1, 10_000_000).Select(_ => new MyInt(r.Next()));
然后OrderBy
将比List.Sort
方法快2倍。
请注意,如果您使用Comparer<>.Create
为Comparer
创建MyInt
,则List.Sort
与OrderBy
差不多:
l.Sort(Comparer<MyInt>.Create((m1,m2) => m1.value.CompareTo(m2.value)));