C# 为什么列表<>;。OrderBy LINQ比IComparable快+;列表<>;。在调试模式下排序?
我感兴趣的是,使用LINQ还是通过实现IComparable接口和List.sort对类进行排序会更快。当LINQ代码更快时,我非常惊讶 为了进行测试,我创建了一个非常简单的类,使用不太合适的名称TestSort,实现了IComparableC# 为什么列表<>;。OrderBy LINQ比IComparable快+;列表<>;。在调试模式下排序?,c#,linq,sorting,benchmarking,C#,Linq,Sorting,Benchmarking,我感兴趣的是,使用LINQ还是通过实现IComparable接口和List.sort对类进行排序会更快。当LINQ代码更快时,我非常惊讶 为了进行测试,我创建了一个非常简单的类,使用不太合适的名称TestSort,实现了IComparable class TestSort: IComparable<TestSort> { private int age; private string givenName; public int Age {
class TestSort: IComparable<TestSort> {
private int age;
private string givenName;
public int Age {
get {
return age;
}
set {
age = value;
}
}
public string GivenName {
get {
return givenName;
}
set {
givenName = value;
}
}
public TestSort(int age, string name) {
this.age = age;
this.givenName = name;
}
public int CompareTo(TestSort other) {
return this.age.CompareTo(other.age);
}
}
但是我仍然很想知道为什么IComparable在调试模式下速度较慢。如果在开始测量之前确保所有内容都是JIT的,那么可能会得到不同的结果(我还建议使用
秒表
类来测量时间):
根据我的测量(添加上述代码后),IComparable总是更快(即使在调试中)。这可能是调用方法
CompareTo
的开销,当编译并在发布模式下运行时,该方法将被内联替换。排序使用未优化的快速排序,在最坏的情况下,它的复杂性是n*n。我不知道orderby使用了什么,但我知道它没有使用相同的方法,因为它是一种稳定的排序,不像数组。sort
对于我来说,我将使用Linq和IComparable(当这是最常用或唯一的排序方法时)。在本例中,项是一个TestSort:IComparable
ll
可以是任何IEnumerable:列表、数组等
此外,在compare to
中,您可以使用多种方式来比较。。。例如,您可以执行以下操作:
public int CompareTo(TestSort other) {
return this.age != other.age ? this.age.CompareTo(other.age) : this.dateOfBirth.CompareTo(other.dateOfBirth);
}
您是否尝试过在调试模式(项目属性)下设置优化,并查看其是否仍然较慢?如果没有,那就可以解释了。优化代码已打开。。。我在寻找一个实际的原因,而不是一个促成因素。我不是想解决这个问题,这两种方法对于我来说都足够快了,我只是想知道为什么。你如何确保在测量之前事情都是JIT的?还有。在我的电脑上进行大约900次测试,IComparable速度更快。但如果循环次数超过1000次,LINQ会变得更快。因此,初始LINQ设置会有一些开销,但重复使用最终会更快。在代码段中,当您调用
ll.OrderBy()
时,列表已在前一行排序,因此调用OrderBy()
时,可能需要进行的计算更少。您能否验证在秒表测试中,您没有对已排序的列表调用OrderBy()
?@lorddev此代码仅用于JIT方法,因此实际测量将更加准确。然而,现在最好只使用.Linq to objects OrderBy使用稳定的快速排序,而不是使用不稳定的快速排序的Array.Sort。算法的速度代价应该没有太大的差别。它们都是O(n logn)。您知道它是优化的还是仍然是相同的n^2最坏情况吗?
IComparable<T>:
2965.1696
LINQ:
2181.1248
IComparable<T>:
1593.0911
Linq:
1958.1119
var ll = ts2.ToList();
ll.Sort();
ll.OrderBy(item => item.Age).ToList();
var sorted = ll.OrderBy(item => item); // This automatically used age to compare, as it's defined in CompareTo
public int CompareTo(TestSort other) {
return this.age != other.age ? this.age.CompareTo(other.age) : this.dateOfBirth.CompareTo(other.dateOfBirth);
}