Last active
March 4, 2019 03:46
-
-
Save nycdotnet/008ed7a417b6dca119323e25eb7aabe4 to your computer and use it in GitHub Desktop.
ImmutableDictionary vs ReadOnlyDictionary vs Dictionary Benchmarks with .NET Core SDK 3.0-preview2
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
BenchmarkDotNet=v0.11.4, OS=Windows 10.0.17134.590 (1803/April2018Update/Redstone4) | |
Intel Core i7-6600U CPU 2.60GHz (Skylake), 1 CPU, 4 logical and 2 physical cores | |
.NET Core SDK=3.0.100-preview-010184 | |
[Host] : .NET Core 2.1.8 (CoreCLR 4.6.27317.03, CoreFX 4.6.27317.03), 64bit RyuJIT | |
MediumRun : .NET Core 3.0.0-preview-27324-5 (CoreCLR 4.6.27322.0, CoreFX 4.7.19.7311), 64bit RyuJIT | |
Job=MediumRun Toolchain=.NET Core 3.0 Preview 2 InvocationCount=1 | |
IterationCount=15 LaunchCount=2 UnrollFactor=1 | |
WarmupCount=10 | |
| Method | ItemCount | Mean | Error | StdDev | Median | Rank | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | | |
|----------------------------- |---------- |--------------:|-----------:|-------------:|--------------:|-----:|------------:|------------:|------------:|--------------------:| | |
| ConstructDictionary | 0 | 5.366 us | 1.750 us | 2.510 us | 4.645 us | 1 | - | - | - | 72 B | | |
| ConstructReadOnlyDictionary | 0 | 6.456 us | 2.763 us | 3.963 us | 5.760 us | 1 | - | - | - | 112 B | | |
| ConstructImmutableDictionary | 0 | 5.790 us | 2.451 us | 3.516 us | 4.665 us | 1 | - | - | - | - | | |
| ConstructDictionary | 10 | 9.611 us | 3.122 us | 4.477 us | 7.920 us | 2 | - | - | - | 464 B | | |
| ConstructReadOnlyDictionary | 10 | 10.753 us | 3.213 us | 4.808 us | 9.945 us | 2 | - | - | - | 472 B | | |
| ConstructImmutableDictionary | 10 | 20.787 us | 4.859 us | 7.123 us | 20.700 us | 4 | - | - | - | 712 B | | |
| ConstructDictionary | 100 | 17.703 us | 5.834 us | 8.732 us | 13.573 us | 3 | - | - | - | 3152 B | | |
| ConstructReadOnlyDictionary | 100 | 16.308 us | 4.848 us | 7.107 us | 13.310 us | 3 | - | - | - | 3160 B | | |
| ConstructImmutableDictionary | 100 | 88.680 us | 15.268 us | 22.380 us | 80.850 us | 6 | - | - | - | 6472 B | | |
| ConstructDictionary | 1000 | 64.033 us | 6.319 us | 8.859 us | 60.960 us | 5 | - | - | - | 31040 B | | |
| ConstructReadOnlyDictionary | 1000 | 68.881 us | 10.945 us | 15.697 us | 65.830 us | 5 | - | - | - | 31048 B | | |
| ConstructImmutableDictionary | 1000 | 924.743 us | 78.464 us | 115.011 us | 887.775 us | 9 | - | - | - | 64072 B | | |
| ConstructDictionary | 10000 | 716.794 us | 124.657 us | 178.779 us | 642.448 us | 8 | - | - | - | 283040 B | | |
| ConstructReadOnlyDictionary | 10000 | 618.567 us | 30.743 us | 43.097 us | 612.950 us | 7 | - | - | - | 283048 B | | |
| ConstructImmutableDictionary | 10000 | 11,354.698 us | 943.558 us | 1,412.274 us | 11,559.440 us | 10 | - | - | - | 640072 B | |
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
BenchmarkDotNet=v0.11.4, OS=Windows 10.0.17134.590 (1803/April2018Update/Redstone4) | |
Intel Core i7-6600U CPU 2.60GHz (Skylake), 1 CPU, 4 logical and 2 physical cores | |
.NET Core SDK=3.0.100-preview-010184 | |
[Host] : .NET Core 2.1.8 (CoreCLR 4.6.27317.03, CoreFX 4.6.27317.03), 64bit RyuJIT | |
MediumRun : .NET Core 3.0.0-preview-27324-5 (CoreCLR 4.6.27322.0, CoreFX 4.7.19.7311), 64bit RyuJIT | |
Job=MediumRun Toolchain=.NET Core 3.0 Preview 2 InvocationCount=1 | |
IterationCount=15 LaunchCount=2 UnrollFactor=1 | |
WarmupCount=10 | |
| Method | LookupCount | Mean | Error | StdDev | Median | Rank | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | | |
|--------------------------- |------------ |---------------:|-------------:|-------------:|---------------:|-----:|------------:|------------:|------------:|--------------------:| | |
| DictionaryLookups | 1 | 1,253.8 ns | 698.7 ns | 956.3 ns | 827.5 ns | 1 | - | - | - | - | | |
| ReadOnlyDictionaryLookups | 1 | 889.0 ns | 656.1 ns | 898.0 ns | 855.0 ns | 1 | - | - | - | - | | |
| ImmutableDictionaryLookups | 1 | 4,287.1 ns | 2,328.6 ns | 3,413.2 ns | 2,275.0 ns | 3 | - | - | - | - | | |
| DictionaryLookups | 10 | 1,574.3 ns | 940.0 ns | 1,348.1 ns | 1,265.0 ns | 1 | - | - | - | - | | |
| ReadOnlyDictionaryLookups | 10 | 2,075.4 ns | 671.5 ns | 941.4 ns | 1,725.0 ns | 2 | - | - | - | - | | |
| ImmutableDictionaryLookups | 10 | 6,058.3 ns | 1,984.8 ns | 2,970.8 ns | 5,605.0 ns | 4 | - | - | - | - | | |
| DictionaryLookups | 100 | 6,910.6 ns | 1,509.2 ns | 2,115.8 ns | 5,905.0 ns | 4 | - | - | - | - | | |
| ReadOnlyDictionaryLookups | 100 | 8,153.0 ns | 2,126.4 ns | 2,980.9 ns | 6,880.0 ns | 5 | - | - | - | - | | |
| ImmutableDictionaryLookups | 100 | 21,223.4 ns | 3,038.1 ns | 4,357.1 ns | 19,710.0 ns | 6 | - | - | - | - | | |
| DictionaryLookups | 1000 | 48,210.8 ns | 3,230.2 ns | 4,834.8 ns | 47,777.5 ns | 7 | - | - | - | - | | |
| ReadOnlyDictionaryLookups | 1000 | 62,172.9 ns | 11,886.9 ns | 17,047.8 ns | 55,215.0 ns | 8 | - | - | - | - | | |
| ImmutableDictionaryLookups | 1000 | 191,542.5 ns | 28,352.2 ns | 42,436.3 ns | 174,975.0 ns | 9 | - | - | - | - | | |
| DictionaryLookups | 10000 | 562,560.0 ns | 138,506.9 ns | 207,310.5 ns | 486,120.0 ns | 10 | - | - | - | - | | |
| ReadOnlyDictionaryLookups | 10000 | 538,170.0 ns | 46,724.1 ns | 65,500.7 ns | 517,500.0 ns | 10 | - | - | - | - | | |
| ImmutableDictionaryLookups | 10000 | 2,157,841.7 ns | 499,166.3 ns | 731,671.4 ns | 1,759,565.0 ns | 11 | - | - | - | - | |
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
[RankColumn, MemoryDiagnoser] | |
public class StringKeyDictionaryConstructionBenchmark | |
{ | |
private KeyValuePair<string, int>[] _items; | |
[Params(0, 10, 100, 1000, 10000)] | |
public int ItemCount; | |
[IterationSetup] | |
public void IterationSetup() | |
{ | |
_items = Enumerable | |
.Range(0, ItemCount) | |
.Select(_ => new KeyValuePair<string, int>(Guid.NewGuid().ToString(), 0)) | |
.ToArray(); | |
} | |
[Benchmark] | |
public Dictionary<string, int> ConstructDictionary() => | |
new Dictionary<string, int>(_items); | |
[Benchmark] | |
public ReadOnlyDictionary<string, int> ConstructReadOnlyDictionary() => | |
new ReadOnlyDictionary<string, int>(_items.ToDictionary(i => i.Key, i => i.Value)); | |
[Benchmark] | |
public ImmutableDictionary<string, int> ConstructImmutableDictionary() => | |
ImmutableDictionary.ToImmutableDictionary(_items); | |
} |
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
[RankColumn, MemoryDiagnoser] | |
public class StringKeyDictionaryLookupBenchmark | |
{ | |
private KeyValuePair<string, int>[] _items; | |
private int[] _result; | |
private Dictionary<string, int> _dictionary; | |
private ReadOnlyDictionary<string, int> _readOnlyDictionary; | |
private ImmutableDictionary<string, int> _immutableDictionary; | |
public int DictionarySize = 100; | |
[Params(1, 10, 100, 1000, 10000)] | |
public int LookupCount; | |
public void AllIterationSetup() | |
{ | |
_items = Enumerable | |
.Range(0, DictionarySize) | |
.Select(_ => new KeyValuePair<string, int>(Guid.NewGuid().ToString(), 1)) | |
.ToArray(); | |
_result = new int[LookupCount]; | |
} | |
[IterationSetup(Targets = new[] { nameof(DictionaryLookups) })] | |
public void SetupDictionaryLookups() | |
{ | |
AllIterationSetup(); | |
_dictionary = new Dictionary<string, int>(_items); | |
} | |
[IterationSetup(Targets = new[] { nameof(ReadOnlyDictionaryLookups) })] | |
public void SetupReadOnlyDictionaryLookups() | |
{ | |
AllIterationSetup(); | |
_readOnlyDictionary = new ReadOnlyDictionary<string, int>(_items.ToDictionary(i => i.Key, i => i.Value)); | |
} | |
[IterationSetup(Targets = new[] { nameof(ImmutableDictionaryLookups) })] | |
public void SetupImmutableDictionaryLookups() | |
{ | |
AllIterationSetup(); | |
_immutableDictionary = ImmutableDictionary.ToImmutableDictionary(_items); | |
} | |
[IterationCleanup] | |
public void Assert() | |
{ | |
if (!_result.All(v => v == 1)) | |
{ | |
throw new ApplicationException($"Expected all results to have been set to 1."); | |
} | |
} | |
[Benchmark] | |
public int[] DictionaryLookups() => PerformLookupsForBenchmark(_dictionary); | |
[Benchmark] | |
public int[] ReadOnlyDictionaryLookups() => PerformLookupsForBenchmark(_readOnlyDictionary); | |
[Benchmark] | |
public int[] ImmutableDictionaryLookups() => PerformLookupsForBenchmark(_immutableDictionary); | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
private int[] PerformLookupsForBenchmark<T>(T dict) where T : IDictionary<string, int> | |
{ | |
var i = 0; | |
while (i < LookupCount) | |
{ | |
for (var j = 0; j < DictionarySize; j++) | |
{ | |
_result[i] = dict[_items[j].Key]; | |
i++; | |
if (i == LookupCount) | |
{ | |
break; | |
} | |
} | |
} | |
return _result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment