views:

181

answers:

2

I was interested in whether it would be faster to sort my classes using LINQ, or by implementing the IComparable interface and List.Sort. I was quite surprised when the LINQ code was faster.

To do the test, I made a very simple class with the not-so-apt name of TestSort, implementing 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);
    }
}

Then a simple program to sort it many times - the sort was much more expensive than copying the list, so the effect of that can be ignored.

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

I was quite surprised to receive the following output:

IComparable<T>:
2965.1696

LINQ:
2181.1248

Sometimes LINQ would go below 2000, and sometimes IComparable would go about 3000.

When I tested it with a normal List<Int> the List.Sort was 1/4 the speed of LINQ, which remained at about 2000.

So why is LINQ only about 66% the speed of the normal sort for my class? Am I doing something wrong with my implementation of IComparable?

Update: I just thought to try doing it in release mode, and yes, the results were different:

IComparable<T>:
1593.0911

Linq:
1958.1119

But I am still very interested to know why IComparable is slower in debug mode.

+2  A: 

If you make sure everything is JITed before starting the measure, you might get different results (I also recommend using the Stopwatch class to measure time):

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

According to my measurements (after adding the above code), IComparable is always faster (even in debug).

Aelij Arbel
How do you make sure that things are JITed before measuring?
Vincent McNabb
Also. Doing the test up to about 900 times on my PC, the IComparable is faster. But if I loop more than 1000, then LINQ becomes faster. So there is some overhead on the initial LINQ setup, but repeated uses end up being faster.
Vincent McNabb
A: 

Could it be the overhead of calling the method CompareTo which would be replaced with an inline which would compile in release mode?

sgmoore