Created
October 21, 2014 18:07
-
-
Save copernicus365/df386f7fd581e5577895 to your computer and use it in GitHub Desktop.
Test performance of a Dictionary with enum key, against Dictionary with int key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
namespace EnumTest | |
{ | |
/// <summary> | |
/// Test to discover how well enum lookups are handled in a Dictionary. | |
/// Is it a lot faster to work with an int instead? | |
/// I.e. | |
/// <![CDATA[ | |
/// Dictionary<int, xyz> instead of Dictionary<MyCoolEnum,xyz> ? | |
/// ]]> | |
/// RESULTS! To my surprise, not only does the enum-dictionary | |
/// (dictionary with a enum as its key) perform as fast as when an interger | |
/// is its key, it even edges it out by a bit. WIth an integer dict, | |
/// to do lookups we have to cast the enum to an int, but: 1) I thought that | |
/// would be incredibly fast, and perfectly optimized by the compiler anyways, | |
/// and 2) the enum dict would internally need to do this anyways. My HOPE | |
/// was that .NET team had basically done this under the hood, cast enums | |
/// to int for you, making them of identical performance. Well somehow they | |
/// even edge that out by a tiny bit. So this is very good news. Never again | |
/// be timid about setting an enum as a Dictionary key, when focused on best | |
/// lookup speeds. | |
/// </summary> | |
public class TestEnumDict | |
{ | |
public int Count; | |
public Eval[] types; | |
public int typesLen; | |
public Dictionary<int, Eval> intDict; | |
public Dictionary<Eval, Eval> enumDict; | |
Eval[] typesArray; | |
Eval lastVal; | |
public TestEnumDict(int count) | |
{ | |
Count = count; | |
intDict = new Dictionary<int, Eval>(); | |
enumDict = new Dictionary<Eval, Eval>(); | |
types = Enum.GetValues(typeof(Eval)).Cast<Eval>().ToArray(); // XEnum<Eval>.Values; | |
// SKIP last value (make sure enum has at least 4 vals) so we can ensure optimizations later don't mess results | |
lastVal = types.Last(); | |
types = types.Take(types.Length - 1).ToArray(); | |
typesLen = types.Length; | |
foreach (Eval type in types) { | |
intDict[(int)type] = type; | |
enumDict[type] = type; | |
} | |
typesArray = new Eval[Count]; | |
for (int i = 0, j = 0; i < typesArray.Length; i++) { | |
if (j >= typesLen) j = 0; | |
typesArray[i] = types[j++]; | |
} | |
} | |
public static void TestRun() | |
{ | |
int count = 1000; // 10 million | |
var test = new TestEnumDict(count); | |
var result1 = test.RunRoundToString(); | |
var result2 = test.RunRoundToString(); | |
var result3 = test.RunRoundToString(); | |
var result4 = test.RunRoundToString(); | |
var result5 = test.RunRoundToString(); | |
var result6 = test.RunRoundToString(); | |
Console.ReadLine(); | |
} | |
public string RunRoundToString() | |
{ | |
var val = RunRound(); | |
return string.Format("EnumDict Run: {0}ms\r\nIntDict Run: {1}ms", val.Key.TotalMilliseconds, val.Value.TotalMilliseconds); | |
} | |
public KeyValuePair<TimeSpan, TimeSpan> RunRound() | |
{ | |
var sw = Stopwatch.StartNew(); | |
int len = typesArray.Length; | |
for (int i = 0; i < len; i++) { | |
Eval val = enumDict[typesArray[i]]; | |
if (val == lastVal) | |
throw new Exception(); | |
} | |
TimeSpan enumDictTime = sw.Elapsed; | |
Console.WriteLine("RUN EnumDict: {0}ms", enumDictTime.TotalMilliseconds); | |
sw = Stopwatch.StartNew(); | |
for (int i = 0; i < len; i++) { | |
Eval val = intDict[(int)typesArray[i]]; | |
if (val == lastVal) | |
throw new Exception(); | |
} | |
TimeSpan intDictTime = sw.Elapsed; | |
Console.WriteLine("RUN IntDict: {0}ms", intDictTime.TotalMilliseconds); | |
return new KeyValuePair<TimeSpan, TimeSpan>(enumDictTime, intDictTime); | |
} | |
} | |
public enum Eval | |
{ | |
Val01, Val02, Val03, Val04, Val05, Val06, | |
//Val07, Val08, Val09, Val10, Val11, Val12, | |
//Val13, Val14, Val15, Val16, Val17, Val18, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment