wtorek, 24 kwietnia 2012

LINQ vs IComparable czas sortowania / performance

Zrobiłem mały test.
Chciałem sprawdzić co jest wydajniejsze, LINQ czy użycie IComparera.
Odpowiedź: "to zależy?"


Na początek zrobiłem małą klasę obiektu do testowania, która wyglądała tak:
Następnie w głównej pętli programu napisałem następujący kod:

static void Main(string[] args)
{
    string name = "Mr. Tomek";

    Random r = new Random();
    int size = 50;

    Stopwatch stopWatch = new Stopwatch();

    while (size < 1000000)
    {
        int linqTime = 0;
        int sortTime = 0;

        int repeats = 10;
        Console.WriteLine("Size = {0}", size);

        for (int a = 0; a < repeats; ++a)
        {
            Person[] people1 = new Person[size];
            Person[] people2 = new Person[size];

            for (int i = 0; i < size; i++)
            {
                people1[i] = new Person();
                people1[i].Age = r.Next(0, 10000);
                people1[i].Name = name;

                people2[i] = new Person();
                people2[i].Age = people1[i].Age;
                people2[i].Name = people1[i].Name;
            }

            stopWatch.Start();
            Array.Sort(people1);
            stopWatch.Stop();
            sortTime += (int)stopWatch.ElapsedMilliseconds;

            stopWatch.Start();
            var sort = from p in people2
                        orderby p.Age
                        select p;
            var x = sort.ToArray();
            //Console.WriteLine(x[0].Name + " " + x[0].Age);
            stopWatch.Stop();
            linqTime += (int)stopWatch.ElapsedMilliseconds;
        }

        Console.WriteLine("IComparable: {0}", sortTime/repeats);
        Console.WriteLine("LINQ: {0}", linqTime/repeats);
        Console.WriteLine();
        size += size;
    }

    Console.WriteLine("Measurments done");
    Console.ReadLine();
}
Tworzone są kolejno 2 tablice z losowymi wartościami "Age" dla każdego obiektu person a następnie sortowane przy pomocy LINQ i Array.Sort wykorzystująca IComparer.

Okazało się że wydajność LINQ i Array.Sort zależała od tego, co było wcześniej!
Obie metody pracowały prawie tak samo długo, lecz sortowanie, które było pierwsze w kodzie (w tym przypadku sortowanie przy pomocy IComparera) przebiegało szybciej!

Jeśli by zamienić miejscami bloki kodu odpowiadające za sortowanie LINQ i Array.Sort:
            stopWatch.Start();
            var sort = from p in people2
                        orderby p.Age
                        select p;
            var x = sort.ToArray();
            //Console.WriteLine(x[0].Name + " " + x[0].Age);
            stopWatch.Stop();
            linqTime += (int)stopWatch.ElapsedMilliseconds;


            stopWatch.Start();
            Array.Sort(people1);
            stopWatch.Stop();
            sortTime += (int)stopWatch.ElapsedMilliseconds;

okazałoby się, że tym razem nieznacznie wygrywało LINQ!

Wszystko stało się jasne, gdy dopisałem parę linijek kodu zapisującego wyniki do pliku CSV i wygenerowałem wykresy w Excelu:

Porównanie czasu sortowania:



Stosunek czasów sortowania LINQ / IComparer





Jednak nie potrafię wyjaśnić czemu tak się dzieje...

Brak komentarzy:

Prześlij komentarz