代码之家  ›  专栏  ›  技术社区  ›  Vincent McNabb

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

  •  13
  • Vincent McNabb  · 技术社区  · 14 年前

    我感兴趣的是,使用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
    

    当我用一个普通的 List<Int> 这个 List.Sort

    那么为什么LINQ的速度只有我们班正常速度的66%呢?我在实现IComparable时是否做错了什么?

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

    IComparable<T>:
    1593.0911
    
    Linq:
    1958.1119
    

    但我还是很想知道为什么IComparable在调试模式下速度较慢。

    4 回复  |  直到 14 年前
        1
  •  6
  •   Eli Arbel    14 年前

    如果在开始度量之前确保一切都是jit的,那么可能会得到不同的结果(我还建议使用 Stopwatch 课程(测量时间):

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

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

        2
  •  1
  •   Jaider    12 年前

    对我来说,我将使用Linq和IComparable(当这是最常用或唯一的排序方法时)。在本例中,项是 TestSort: IComparable<TestSort>

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

    ll

    也在 CompareTo

      public int CompareTo(TestSort other) {
            return this.age != other.age ? this.age.CompareTo(other.age) : this.dateOfBirth.CompareTo(other.dateOfBirth);
        }
    
        3
  •  1
  •   Michael Petrotta    12 年前

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

        4
  •  0
  •   Alexei Levenkov    8 年前

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