为什么在调试模式下List< >.OrderBy LINQ比IComparable+List< >.Sort快?

eufgjt7s  于 2023-07-31  发布在  其他
关注(0)|答案(4)|浏览(102)

我感兴趣的是,使用LINQ对类进行排序会更快,还是通过实现IComparable接口和List. Sort更快。当我看到LINQ代码更快时,我感到非常惊讶。
为了进行测试,我创建了一个非常简单的类,它的名字不太合适,叫做TestSort,实现了IComparable。

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

字符串
然后用一个简单的程序对它进行多次排序-排序比复制列表要昂贵得多,因此可以忽略其影响。

class Program {
    static void Main(string[] args) {
        // Create the test data
        string name = "Mr. Bob";

        Random r = new Random();
        var ts2 = new List<TestSort>();

        for (int i = 0; i < 100; i++) {
            ts2.Add(new TestSort(r.Next(), name));
        }

        DateTime start, end;

        // Test List<>.Sort
        start = DateTime.Now;
        for (int i = 0; i < 100000; i++) {
            var l = ts2.ToList();
            l.Sort();
        }
        end = DateTime.Now;

        Console.WriteLine("IComparable<T>: ");
        Console.WriteLine((end - start).TotalMilliseconds);

        // Test Linq OrderBy
        start = DateTime.Now;
        for (int i = 0; i < 100000; i++) {
            var l = ts2.ToList();
            l = l.OrderBy(item => item.Age).ToList();
        }
        end = DateTime.Now;

        Console.WriteLine("\nLINQ: ");
        Console.WriteLine((end - start).TotalMilliseconds);

        Console.WriteLine("Finished.");
        Console.ReadKey();
    }
}


我很惊讶地收到以下输出:

IComparable<T>:
2965.1696

LINQ:
2181.1248


有时LINQ会低于2000,有时IComparable会达到3000左右。
当我用普通的List<Int>测试时,List.Sort的速度是LINQ的1/4,LINQ的速度保持在2000左右。
那么,为什么LINQ的速度只有我的类的正常排序的66%左右呢?我的IComparable实现有什么问题吗?

**更新:**我只是想在发布模式下尝试一下,是的,结果是不同的:

IComparable<T>:
1593.0911

Linq:
1958.1119


但是我仍然非常有兴趣知道为什么IComparable在调试模式下会变慢。

um6iljoc

um6iljoc1#

如果在开始度量之前确保所有内容都已JIT化,则可能会得到不同的结果。我还强烈推荐使用BenchmarkDotNet进行微基准测试。

var ll = ts2.ToList();
ll.Sort();
ll.OrderBy(item => item.Age).ToList();

字符串
根据我的测量(在添加上述代码之后),IComparable总是更快(即使在调试中)。

ctrmrzij

ctrmrzij2#

对我来说,我将使用Linq与IComparable(当这是最多或唯一的排序方式时)。在本例中,item为TestSort: IComparable<TestSort>

var sorted = ll.OrderBy(item => item); // This automatically used age to compare, as it's defined in CompareTo

字符串
ll可以是任何IEnumerable:列表、数组等
此外,在CompareTo中,您可以有多种方式来比较...例如,你可以这样做:

public int CompareTo(TestSort other) {
        return this.age != other.age ? this.age.CompareTo(other.age) : this.dateOfBirth.CompareTo(other.dateOfBirth);
    }

8fq7wneg

8fq7wneg3#

排序使用未优化的快速排序,在最坏的情况下具有n*n的复杂度。我不知道orderby使用了什么,但我知道它没有使用相同的方法,因为它是一个稳定的排序,不像array.sort

qyswt5oh

qyswt5oh4#

这可能是调用方法CompareTo的开销,当在发布模式下编译和运行时,该方法将被替换为内联。

相关问题