About Me

My photo
Kozyatağı, İstanbul, Türkiye

Saturday, February 8, 2014

Reducing Memory Consumption of .NET Dictionary Class


.NET programmers generally use parameterless constructor of .NET Dictionary class. Actually, the class has various constructors. Here I am focused on the one, which takes the initial capacity as parameter.

Using public Dictionary(int capacity)constructor, reduces memory consumption of instance dramatically.

To measure the difference clearly, we create here 2 dictionaries of type Dictionary<long, string>;
n  One with unknown capacity,
n  One with known capacity

We add 1 million items to each of them. Here are the results:












Code:

using System;
using System.Collections.Generic;

namespace caDictionaryMemory
{
    class Program
    {
        const int length = 1000000;
        static void Main(string[] args)
        {
            Dictionary<long, string> dictWithCapacity = new Dictionary<long, string>(length);
            long lengthWithCapacity = AddItemsAndFindMemoryUsage(dictWithCapacity, length);

            Dictionary<long, string> dictWithoutCapacity = new Dictionary<long, string>();
            long lengthWithoutCapacity = AddItemsAndFindMemoryUsage(dictWithoutCapacity, length);
            Console.WriteLine("Memory Usage When Capacity Known: {0:0,0} KB", lengthWithCapacity);
            Console.WriteLine("Memory Usage When Capacity Unknown: {0:0,0} KB", lengthWithoutCapacity);
            Console.WriteLine();
            // Dummy usage of dictionaries to prevent Garbage Collector to collect them.
            Console.WriteLine("Item Count When Capacity Known: {0:0,0}", dictWithCapacity.Count);
            Console.WriteLine("Item Count When Capacity Unknown: {0:0,0}", dictWithoutCapacity.Count);
        }

        static long AddItemsAndFindMemoryUsage(Dictionary<long, string> dict, int count)
        {
            long beforeBytes = GC.GetTotalMemory(true);
            for (int i = 0; i < count; i++)
            {
                dict.Add(i, i.ToString());
            }
            long afterBytes = GC.GetTotalMemory(true);
            return (afterBytes - beforeBytes) / 1024;
        }
    }
}

The dictionary with unknown capacity uses 221% memory compared to known one.