Immutable Collections Performance #dotnet

Yesterday ayende blogged and tweeted about serious issues with Immutable collections performance. whilst I didn’t have time to really look into it, I did retweet the link and got involved in a discussion with ex-softie Brandon Paddock.

When I woke up, I saw some more discussion and thought, let me try it myself. Now we all know every chef has their own way and some ways are better than others. FYI, I never used ImmutableCollections before this date and it took me a few mins to get the hang of it.

so what did I do ? I kept it simple. Here’s the source and the results. As you can see creating immutable collection is an added option and that takes time but its not very high

class Program
{
    static int MaxIterations = 10 * 1000 * 1000;
    static int maxRuns = 5;
    static void Main(string[] args)
    {
        for (int i = 0; i < maxRuns; i++ )
        {
            GC.Collect();

            TestGenericList();

            GC.Collect();

            TestImmutableList();
        }
    }

    public static void PreRunWarmup()
    {
        List<int> genericDataList = new List<int>();

        for (int i = 0; i < MaxIterations; i++)
        {
            genericDataList.Add(i);
        }

        genericDataList.Clear();
        genericDataList = null;
    }

    public static void TestGenericList()
    {
        List<int> genericDataList = new List<int>();
                        
        var sw = Stopwatch.StartNew();
        for (int i = 0; i < MaxIterations; i++)
        {
            genericDataList.Add(i);
        }

        sw.Stop();
        Console.WriteLine("Generic List took {0} ms", (double)sw.ElapsedTicks * (double)1000 / (double)Stopwatch.Frequency);

        genericDataList.Clear();
        genericDataList = null;
    }

    public static void TestImmutableList()
    {
        List<int> genericDataList = new List<int>();

        var sw = Stopwatch.StartNew();
        for (int i = 0; i < MaxIterations; i++)
        {
            genericDataList.Add(i);
        }

        ImmutableList<List<int>> immutableList = ImmutableList.Create(genericDataList);

        sw.Stop();
        Console.WriteLine("Immutable List took {0} ms", (double)sw.ElapsedTicks * (double)1000 / (double)Stopwatch.Frequency);

        genericDataList.Clear();
        genericDataList = null;
    }
}

and the results are

Generic List took 85.5857446744927 ms
Immutable List took 88.5216447923091 ms
Generic List took 89.7324092764301 ms
Immutable List took 88.4739507537922 ms
Generic List took 88.1856734956681 ms
Immutable List took 90.4921934216639 ms
Generic List took 85.6533615392255 ms
Immutable List took 88.9282515637155 ms
Generic List took 87.9722577663554 ms
Immutable List took 84.6940472708294 ms
Press any key to continue . . .

Note: I added a pre-test warm up as the first iteration was taking unusually long.
So for a few more milli-seconds per million entries what do we get ?

If you have a threaded environment and you pass collection and iterate them, you should have come across the infamous InvalidOperationException stating something like “Collection was modified; enumeration operation may not execute.” At least I have resorted to using lock around collection enumeration code in past.
With immutable collection, you never have to worry about the output received from Immutable.CreateList. No more unnecessary locks around iterations.

Note: I used GC.Collect excessively and even resorted to cleaning and setting collections to null so as to not impact the next call. Just pure perf test.

About these ads

2 thoughts on “Immutable Collections Performance #dotnet

  1. Hermit,
    What you are doing is to create a _snapshot_ of the data.
    That is nice, but it is utterly useless. Try to imagine that you now need to do this in another operation (for example, you need to track something).
    That means that you cannot build the entire data set in one go.

    Snapshot != immutable.

    For fun, try iterating over both of lists, for AND foreach are _horrible_

    • Based on my near realtime system usage, the way i’d use immutable is creating snapshot of changing data and using that for each iteration. My experience has been pretty one sided in terms of high volume systems – driven by need for speed.

      I will have a go at creating a better sample soon. Possibly threaded and one updating data and one iterating to at least exercise my previous collection usage patterns

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s