Saturday, January 5, 2008

Dictionary Performance

I tested performances of these classes :

A) Key-value keepers
- Dictionary
- SortedDictionary
- SortedList
B) Value keepers
- List
- HashSet
- List (Sorted and binary searched)

I inserted a number of random numbers to these classes and searched for numbers afterwards.
Below results show the average of 100 tests.





Item Count510501001,00010,000
OperationInsert (µs)Search (µs)Insert (µs)Search (µs)Insert (µs)Search (µs)Insert (µs)Search (µs)Insert (µs)Search (µs)Insert (µs)Search (µs)
Key-Value Holders(string - string)Dictionary3.9712.814.3311.208.7515.1012.7820.04111.49116.071,037.951,082.61
SortedDictionary2.272.596.956.3065.4348.79131.48134.952,133.921,936.4729,699.9727,179.20
SortedList2.673.586.596.7582.5162.68116.64115.662,747.471,772.13115,544.2724,216.48
Value Holders(string)List2.4612.042.6011.893.6142.944.62141.0533.4411,644.09263.981,166,795.60
HashSet0.841.671.331.706.535.939.7610.8478.95103.39914.991,085.26
List(Sorted)9.417.3718.3811.4295.6361.45184.43112.952,353.521,687.8431,121.1923,464.25





For value holder classes :
- ICollection.Add(item) method is used to insert items.
- ICollection.Contains(item) method is used to search for items

For key-value holder classes
- IDictionary.Add(key, item) method is used to insert items.
- IDictionary.ContainsKey(key) method is used to search for items.


RESULTS


If you want to keep key-value pairs, you obviously want to do search business.


If you keep less than 10 items of key-value pairs, search performance of sorted dictionary is the best. Above 10 items dictionary beats others in search business.


If you want to keep only values, there are two businesses : transferring the data, or searching the data.


If you are to insert the items to a list, transfer them to some other method, and in theat method you loop through all items, List is the best tool.


If you are to insert items to some list and to do checks of existence on that list, HashSet is the best tool.




Edit : You may find the code here :


using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Collections;

namespace ConsoleApp
{



public static class Program2
{

private static void DebugWriteLine(string message, int testCount, VoidMethod method)
{
Stopwatch t2 = new Stopwatch();
t2.Start();
for (int j = 0; j < testCount; j++)
{
method();
}
t2.Stop();
Console.WriteLine(message + "\t" + ((t2.Elapsed.TotalSeconds * 1000000) / testCount).ToString("0.###############"));
}

private static void TestDictionaryInsert<T>(T dict, List<string> items) where T : IDictionary<string, string>
{
foreach (var item in items)
{
dict.Add(item, item);
}
}

private static void TestDictionarySearch<T>(T dict, List<string> items) where T : IDictionary<string, string>
{
foreach (var item in items)
{
dict.ContainsKey(item);
}
}

private static void TestListInsert<T>(T list, List<string> items) where T : ICollection<string>
{
foreach (var item in items)
{
list.Add(item);
}
}

private static void TestListSearch<T>(T list, List<string> items) where T : ICollection<string>
{
foreach (var item in items)
{
list.Contains(item);
}
}

static void Main(string[] args)
{
TestPerformanceOfDataHolders(100);
Console.ReadKey();
}

public static void TestPerformanceOfDataHolders(int itemCount)
{
var items = new List<string>(itemCount);

Random r = new Random((int)DateTime.Now.Ticks);
int random = 0;
for (int i = 0; i < itemCount; i++)
{
do
{
random = r.Next();
} while (items.Contains(random.ToString()));
items.Add(random.ToString());
}

List<IDictionary<string, string>> dictList = new List<IDictionary<string, string>>();
dictList.Add(new Dictionary<string, string>());
dictList.Add(new SortedDictionary<string, string>());
dictList.Add(new SortedList<string, string>());

List<ICollection<string>> colList = new List<ICollection<string>>();
colList.Add(new List<string>());
colList.Add(new HashSet<string>());

var sortedList = new List<string>();

foreach (var item in dictList)
{
TestDictionaryInsert(item, items);
}

foreach (var item in colList)
{
TestListInsert(item, items);
}

sortedList.AddRange(items);
sortedList.Sort();

const int testCount = 100;
foreach (var item in dictList)
{
DebugWriteLine(item.GetType().Name + " Insert", testCount, delegate
{
item.Clear();
TestDictionaryInsert(item, items);
});
}

foreach (var item in colList)
{
DebugWriteLine(item.GetType().Name + " Insert", testCount, delegate
{
item.Clear();
TestListInsert(item, items);
});
}

DebugWriteLine("List(Sorted) Insert", testCount, delegate
{
sortedList.Clear();
foreach (var item in items)
{
sortedList.Add(item);
}
sortedList.Sort();
});

foreach (var item in dictList)
{
DebugWriteLine(item.GetType().Name + " Search", testCount, delegate
{
TestDictionarySearch(item, items);
});
}

foreach (var item in colList)
{
DebugWriteLine(item.GetType().Name + " Search", testCount, delegate
{
TestListSearch(item, items);
});
}

DebugWriteLine("List(Sorted) Search", testCount, delegate
{
foreach (var item in items)
{
sortedList.BinarySearch(item);
}
});
}



}

}

No comments:

Post a Comment