Created
February 2, 2026 16:48
-
-
Save udlose/180ca444ac0de69c0703a40be06fd212 to your computer and use it in GitHub Desktop.
Dictionary Add with key of type Guid vs string
This file contains hidden or 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
| [MemoryDiagnoser] | |
| [Config(typeof(DictionaryKeyAddBenchmarks.DictionaryKeyAddBenchmarksConfig))] | |
| public class DictionaryKeyAddBenchmarks | |
| { | |
| private readonly Consumer _consumer = new Consumer(); | |
| private Guid[] _guidKeys = Array.Empty<Guid>(); | |
| private string[] _string_20_Keys = Array.Empty<string>(); | |
| private string[] _string_50_Keys = Array.Empty<string>(); | |
| // [Params(5_000, 10_000, 50_000)] | |
| [Params(500, 1_000, 5_000)] | |
| public int DictionarySize { get; set; } | |
| [GlobalSetup] | |
| public void GlobalSetup() | |
| { | |
| int count = DictionarySize; | |
| _guidKeys = new Guid[count]; | |
| for (int i = 0; i < count; i++) | |
| { | |
| _guidKeys[i] = Guid.NewGuid(); | |
| } | |
| _string_20_Keys = CreateUniqueStrings(count, 20, seed: 12345); | |
| _string_50_Keys = CreateUniqueStrings(count, 50, seed: 54321); | |
| } | |
| // baseline enables Ratio (relative factor) | |
| [Benchmark(Baseline = true)] | |
| [MethodImpl(MethodImplOptions.NoInlining)] | |
| public void Add_Guid() | |
| { | |
| // use locals to avoid noise from property reads | |
| int count = DictionarySize; | |
| // create a new dictionary each benchmark run to avoid having to use IterationSetup | |
| // which should NOT be used for microbenchmarks: | |
| // https://benchmarkdotnet.org/articles/features/setup-and-cleanup.html#sample-introsetupcleanupiteration | |
| Dictionary<Guid, int> dictionary = new Dictionary<System.Guid, int>(count); | |
| Guid[] keys = _guidKeys; | |
| Consumer consumer = _consumer; | |
| for (int i = 0; i < count; i++) | |
| { | |
| // add throws on duplicate keys | |
| dictionary.Add(keys[i], i); | |
| consumer.Consume(i); | |
| } | |
| consumer.Consume(dictionary.Count); | |
| } | |
| [Benchmark] | |
| [MethodImpl(MethodImplOptions.NoInlining)] | |
| public void Add_String_20() | |
| { | |
| // use locals to avoid noise from property reads | |
| int count = DictionarySize; | |
| // create a new dictionary each benchmark run to avoid having to use IterationSetup | |
| // which should NOT be used for microbenchmarks: | |
| // https://benchmarkdotnet.org/articles/features/setup-and-cleanup.html#sample-introsetupcleanupiteration | |
| Dictionary<string, int> dictionary = new Dictionary<string, int>(count); | |
| string[] keys = _string_20_Keys; | |
| Consumer consumer = _consumer; | |
| for (int i = 0; i < count; i++) | |
| { | |
| // add throws on duplicate keys | |
| dictionary.Add(keys[i], i); | |
| consumer.Consume(i); | |
| } | |
| consumer.Consume(dictionary.Count); | |
| } | |
| [Benchmark] | |
| [MethodImpl(MethodImplOptions.NoInlining)] | |
| public void Add_String_50() | |
| { | |
| // use locals to avoid noise from property reads | |
| int count = DictionarySize; | |
| // create a new dictionary each benchmark run to avoid having to use IterationSetup | |
| // which should NOT be used for microbenchmarks: | |
| // https://benchmarkdotnet.org/articles/features/setup-and-cleanup.html#sample-introsetupcleanupiteration | |
| Dictionary<string, int> dictionary = new Dictionary<string, int>(count); | |
| string[] keys = _string_50_Keys; | |
| Consumer consumer = _consumer; | |
| for (int i = 0; i < count; i++) | |
| { | |
| // add throws on duplicate keys | |
| dictionary.Add(keys[i], i); | |
| consumer.Consume(i); | |
| } | |
| consumer.Consume(dictionary.Count); | |
| } | |
| private static string[] CreateUniqueStrings(int count, int length, int seed) | |
| { | |
| HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase); | |
| string[] result = new string[count]; | |
| Random random = new Random(seed); | |
| //const string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | |
| const string alphabet = "abcdefghijklmnopqrstuvwxyz"; | |
| int alphabetLength = alphabet.Length; | |
| for (int i = 0; i < count; i++) | |
| { | |
| while (true) | |
| { | |
| char[] chars = new char[length]; | |
| for (int c = 0; c < length; c++) | |
| { | |
| chars[c] = alphabet[random.Next(alphabetLength)]; | |
| } | |
| string candidate = new string(chars); | |
| if (seen.Add(candidate)) | |
| { | |
| result[i] = candidate; | |
| break; | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| private class DictionaryKeyAddBenchmarksConfig : ManualConfig | |
| { | |
| public DictionaryKeyAddBenchmarksConfig() | |
| { | |
| SummaryStyle = BenchmarkDotNet.Reports.SummaryStyle.Default.WithRatioStyle(RatioStyle.Trend); | |
| } | |
| } | |
| } | |
| public static class Program | |
| { | |
| public static void Main(string[] args) | |
| { | |
| BenchmarkRunner.Run<DictionaryKeyAddBenchmarks>(); | |
| } | |
| } |
This file contains hidden or 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
| // Run time: 00:09:49 (589.97 sec), executed benchmarks: 9 | |
| // | |
| // * Summary * | |
| // BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.7628/25H2/2025Update/HudsonValley2) | |
| // AMD Ryzen 9 7945HX with Radeon Graphics 2.50GHz, 1 CPU, 32 logical and 16 physical cores | |
| // | |
| // .NET SDK 10.0.102 | |
| // [Host] : .NET 10.0.2 (10.0.2, 10.0.225.61305), X64 RyuJIT x86-64-v4 | |
| // | |
| //| Method | DictionarySize | Mean | Error | StdDev | Median | Ratio | RatioSD | | |
| //|-------------- |--------------- |-----------:|----------:|----------:|-----------:|-------------:|--------:| | |
| //| Add_Guid | 500 | 2.596 μs | 0.0560 μs | 0.1578 μs | 2.568 μs | baseline | | | |
| //| Add_String_20 | 500 | 4.801 μs | 0.0959 μs | 0.1915 μs | 4.798 μs | 1.86x slower | 0.13x | | |
| //| Add_String_50 | 500 | 7.329 μs | 0.1669 μs | 0.4733 μs | 7.179 μs | 2.83x slower | 0.25x | | |
| //| | | | | | | | | | |
| //| Add_Guid | 1000 | 4.961 μs | 0.0989 μs | 0.2518 μs | 4.897 μs | baseline | | | |
| //| Add_String_20 | 1000 | 8.864 μs | 0.1769 μs | 0.4307 μs | 8.849 μs | 1.79x slower | 0.12x | | |
| //| Add_String_50 | 1000 | 14.653 μs | 0.6094 μs | 1.7485 μs | 13.979 μs | 2.96x slower | 0.38x | | |
| //| | | | | | | | | | |
| //| Add_Guid | 5000 | 91.310 μs | 1.8140 μs | 3.7462 μs | 91.167 μs | baseline | | | |
| //| Add_String_20 | 5000 | 111.300 μs | 2.2225 μs | 6.1215 μs | 111.078 μs | 1.22x slower | 0.08x | | |
| //| Add_String_50 | 5000 | 138.318 μs | 2.7604 μs | 5.7620 μs | 138.342 μs | 1.52x slower | 0.09x | |
This file contains hidden or 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
| // Run time: 00:11:12(672.18 sec), executed benchmarks: 9 | |
| // | |
| // * Summary * | |
| // BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.7628/25H2/2025Update/HudsonValley2) | |
| // AMD Ryzen 9 7945HX with Radeon Graphics 2.50GHz, 1 CPU, 32 logical and 16 physical cores | |
| // | |
| // [Host] : .NET Framework 4.8.1 (4.8.9221.0), X86 LegacyJIT | |
| // DefaultJob : .NET Framework 4.8.1 (4.8.9221.0), X86 LegacyJIT | |
| // | |
| //| Method | DictionarySize | Mean | Error | StdDev | Median | Ratio | RatioSD | | |
| //|-------------- |--------------- |-----------:|----------:|-----------:|-----------:|-------------:|--------:| | |
| //| Add_Guid | 500 | 6.566 μs | 0.1643 μs | 0.4660 μs | 6.564 μs | baseline | | | |
| //| Add_String_20 | 500 | 7.771 μs | 0.2117 μs | 0.6107 μs | 7.570 μs | 1.19x slower | 0.13x | | |
| //| Add_String_50 | 500 | 9.999 μs | 0.1988 μs | 0.4685 μs | 9.980 μs | 1.53x slower | 0.13x | | |
| //| | | | | | | | | | |
| //| Add_Guid | 1000 | 12.915 μs | 0.2508 μs | 0.2788 μs | 12.908 μs | baseline | | | |
| //| Add_String_20 | 1000 | 13.723 μs | 0.2575 μs | 0.3349 μs | 13.753 μs | 1.06x slower | 0.03x | | |
| //| Add_String_50 | 1000 | 20.643 μs | 0.5156 μs | 1.4457 μs | 20.194 μs | 1.60x slower | 0.12x | | |
| //| | | | | | | | | | |
| //| Add_Guid | 5000 | 110.310 μs | 2.2023 μs | 5.8018 μs | 108.866 μs | baseline | | | |
| //| Add_String_20 | 5000 | 108.083 μs | 2.6184 μs | 7.5128 μs | 107.593 μs | 1.03x faster | 0.09x | | |
| //| Add_String_50 | 5000 | 157.940 μs | 5.4328 μs | 15.7615 μs | 158.477 μs | 1.44x slower | 0.16x | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment