Welcome Parallel Linq

Il mio primo test della Beta 2 di Visual Studio 2010 non riguarda ASP.NET ma il mondo del Parallel Programming, e, nello specifico, del Parallel Linq, ossia la possibilità di utilizzare il Parallel Framework tramite la sintassi Linq.

L’utilizzo è semplicissimo e le prestazioni sono da paura se viene fatto un confronto con la stessa operazione ma senza l’utilizzo del Parallel. Ovviamente il test che riporto è banalissimo, ma serve a rendere l’idea di quanto semplice sia l’implementazione di Parallel Linq con il .NET Framework 4.0 e di che tipo di vantaggio si può trarre da un approccio di questo genere.

Come potete vedere dal codice seguente, l’unica differenza nella sintassi Linq è l’utilizzo dell’apposito Extension Method AsParallel() sull’oggetto da ciclare (Items in questo caso).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Parallel;
using System.Diagnostics;
using System.Threading;
using System.Collections;

namespace Imperugo.Test.ParallelLINQ
{
    class Program
    {
        private static IList items = new List();

        static void Main(string[] args)
        {
            PrepareData();

            ParalelTest();
            ClassicTest();

            Console.WriteLine("\nFinished...");
            Console.ReadKey(true);
        }

        private static void ParalelTest()
        {
            var results = from i in items.AsParallel() where i.SubValues.Contains(new Random(1000).Next()) select i;

            Stopwatch sw = Stopwatch.StartNew();
            IList resultsList = results.ToList();
            Console.WriteLine("{0} items", resultsList.Count());
            sw.Stop();

            Console.WriteLine("It Took {0} ms with parallel Linq", sw.ElapsedMilliseconds);
        }

        private static void ClassicTest()
        {
            var results = from i in items where i.SubValues.Contains(new Random(1000).Next()) select i;

            Stopwatch sw = Stopwatch.StartNew();
            IList resultsList = results.ToList();
            Console.WriteLine("{0} items with Linq", resultsList.Count());
            sw.Stop();

            Console.WriteLine("It Took {0} ms", sw.ElapsedMilliseconds);
        }

        static bool IsDivisibleByFive(int i)
        {
            return i % 5 == 0;
        }

        private static void PrepareData()
        {
            for (int i = 0; i < 1000000; i++)
            {
                var item = new DemoEntity
                                                {
                                                    Title = "New Title " + i,
                                                    SubValues = Enumerable.Range(1, 1000)
                                                };

                items.Add(item);
            }
        }
    }
}

Nel test è stata eseguita la stessa operazione due volte, una utilizzando il Parallel Linq (quadrato blu), ed una utilizzando Linq normalmente (quadrato rosso) su di una collection con 1.000.000 di elementi. I tempi richiesti per completare l’operazione sono ovviamente a vantaggio di Parallel Linq che conclude il ciclo con 9276 millisecondi, a differenza dei 16440 richiesti da Linq.

0023

Un aspetto molto interessante può essere lo scenario di utilizzo. Di fatto, per poter trarre vantaggio dall’utilizzo di Parallel Linq lo si deve sfruttare in elementi corposi (nel test ho utilizzato una collection con 1.000.000 di elementi, ma i vantaggi si cominciano a percepire dai 50.000 elementi in poi), altrimenti si rischia di ottenere l’effetto opposto. Ovviamente incide molto anche il numero di processori che si hanno a disposizione.
I dati riportati sono relativi ad un portatile dual core in modalità balanced, ma la differenza si nota.

Ciauz.AsParallel()


Comments