2009-10-02

LINQ - uwaga na temat klauzul 'where'

W poniższym przykładzie zmierzono czas wykonywania kodu w którym występuje wiele klauzul where porównując go do kodu, w którym zastąpiono je jedną klauzulą where.
using System.Linq;
using System.Collections.Generic;

namespace SpeedTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = Enumerable.Range(0, 1000).ToList();

            {
                System.Diagnostics.Stopwatch stopwatch = 
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                    (from num in list
                     where num != 11
                     where num != 12
                     select num).ToList().ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #1: " + 
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            {
                System.Diagnostics.Stopwatch stopwatch = 
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                    (from num in list
                     where num != 11
                     where num != 12
                     where num != 13
                     where num != 14
                     select num).ToList().ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #2: " + 
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            {
                System.Diagnostics.Stopwatch stopwatch = 
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                    (from num in list
                     where num != 11
                     where num != 12
                     where num != 13
                     where num != 14
                     where num != 15
                     where num != 16
                     where num != 17
                     where num != 18
                     select num).ToList().ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #3: " + 
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            {
                System.Diagnostics.Stopwatch stopwatch = 
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                     (from num in list
                     where (num != 11) &&
                           (num != 12)
                     select num).ToList().ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #4: " + 
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            {
                System.Diagnostics.Stopwatch stopwatch = 
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                    (from num in list
                     where (num != 11) &&
                           (num != 12) &&
                           (num != 13) &&
                           (num != 14)
                     select num).ToList().ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #5: " + 
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            {
                System.Diagnostics.Stopwatch stopwatch = 
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                    (from num in list
                     where (num != 11) &&
                           (num != 12) &&
                           (num != 13) &&
                           (num != 14) &&
                           (num != 15) &&
                           (num != 16) &&
                           (num != 17) &&
                           (num != 18)
                     select num).ToList().ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #6: " + 
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            {
                System.Diagnostics.Stopwatch stopwatch =
                    new System.Diagnostics.Stopwatch();
                stopwatch.Start();

                for (int i = 0; i < 10000; i++)
                {
                    List<int> nums = new List<int>();

                    foreach (int num in list)
                    {
                        if ((num != 11) &&
                            (num != 12) &&
                            (num != 13) &&
                            (num != 14) &&
                            (num != 15) &&
                            (num != 16) &&
                            (num != 17) &&
                            (num != 18))
                        {
                            nums.Add(num);
                        }
                    }

                    nums.ToString();
                }

                stopwatch.Stop();

                System.Console.WriteLine(("Time #7: " +
                    stopwatch.ElapsedMilliseconds + " [ms]"));
            }

            System.Console.ReadKey();
        }
    }
}
Wyniki: Time #1: 440 [ms] Time #2: 536 [ms] Time #3: 805 [ms] Time #4: 357 [ms] Time #5: 364 [ms] Time #6: 375 [ms] Time #7: 175 [ms] Widać, że używanie wielu klauzul where ma bardzo negatywny pływ na prędkość kodu. Jeśli zależy nam na szybkim kodzie powinniśmy się ich wystrzegać. Wszystko oczywiście zależy ile takich klauzul będzie wykonywanych. W powyższmy przykładzie jest ich 10 milionów. Korzystanie z wielu klauzul to nawyk jakiego można nabyć podczas obcowania z SQL. Kod taki jest też bardziej czytelny. W ostatnim siódmym przypadku zrezygnowaliśmy z LINQ. Przyspieszenie jest znaczące (375 -> 175).

Brak komentarzy:

Prześlij komentarz