Skip to content

Instantly share code, notes, and snippets.

@mgravell
Created August 22, 2023 11:40
Show Gist options
  • Save mgravell/61c3a892020860a87a3b6cb3ad1687a5 to your computer and use it in GitHub Desktop.
Save mgravell/61c3a892020860a87a3b6cb3ad1687a5 to your computer and use it in GitHub Desktop.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Collections.Frozen;
using System.Collections.ObjectModel;
BenchmarkRunner.Run(typeof(DictionaryTests).Assembly, args: args);
[MemoryDiagnoser]
public class DictionaryTests
{
private ReadOnlyDictionary<string, object?> _rod = null!;
private Dictionary<string, object?> _d = null!;
private FrozenDictionary<string, object?> _fd = null!;
private IReadOnlyDictionary<string, object?> _irod = null!, _id = null!, _ifd = null!;
private string[] _keys = null!;
[Params(1, 10, 100, 1000)]
public int Count { get; set; }
[GlobalSetup]
public void Setup()
{
int count = 0;
var d = new Dictionary<string, object?>();
var rand = new Random(count); // that'll be fine as a seed, too
for (int i = 0; i < count; i++)
{
string key;
do
{
key = InventString(rand);
} while (d.TryAdd(key, null));
}
_id = _d = d;
_irod = _rod = new ReadOnlyDictionary<string, object?>(d);
_ifd = _fd = d.ToFrozenDictionary();
_keys = d.Keys.ToArray();
static unsafe string InventString(Random rand)
{
Span<char> buffer = stackalloc char[64];
var len = rand.Next(0, 64);
for (int i = 0; i < len; i++)
{
buffer[0] = (char)rand.Next(32, 128);
}
return new string(buffer.Slice(0, len));
}
}
[Benchmark]
public void ROD_Foreach()
{
foreach (var kvp in _rod)
{
GC.KeepAlive(kvp.Value);
}
}
[Benchmark]
public void IROD_Foreach()
{
foreach (var kvp in _irod)
{
GC.KeepAlive(kvp.Value);
}
}
[Benchmark]
public void D_Foreach()
{
foreach (var kvp in _d)
{
GC.KeepAlive(kvp.Value);
}
}
[Benchmark]
public void ID_Foreach()
{
foreach (var kvp in _id)
{
GC.KeepAlive(kvp.Value);
}
}
[Benchmark]
public void FD_Foreach()
{
foreach (var kvp in _fd)
{
GC.KeepAlive(kvp.Value);
}
}
[Benchmark]
public void IFD_Foreach()
{
foreach (var kvp in _ifd)
{
GC.KeepAlive(kvp.Value);
}
}
[Benchmark]
public int ROD_FindKeys()
{
int count = 0;
var t = _rod;
foreach (var key in _keys)
if (t.TryGetValue(key, out _)) count++;
return count;
}
[Benchmark]
public int IROD_FindKeys()
{
int count = 0;
var t = _irod;
foreach (var key in _keys)
if (t.TryGetValue(key, out _)) count++;
return count;
}
[Benchmark]
public int D_FindKeys()
{
int count = 0;
var t = _d;
foreach (var key in _keys)
if (t.TryGetValue(key, out _)) count++;
return count;
}
[Benchmark]
public int ID_FindKeys()
{
int count = 0;
var t = _id;
foreach (var key in _keys)
if (t.TryGetValue(key, out _)) count++;
return count;
}
[Benchmark]
public int FD_FindKeys()
{
int count = 0;
var t = _fd;
foreach (var key in _keys)
if (t.TryGetValue(key, out _)) count++;
return count;
}
[Benchmark]
public int IFD_FindKeys()
{
int count = 0;
var t = _ifd;
foreach (var key in _keys)
if (t.TryGetValue(key, out _)) count++;
return count;
}
}
| Method | Count | Mean | Error | StdDev | Allocated |
|-------------- |------ |----------:|----------:|----------:|----------:|
| ROD_Foreach | 1 | 3.5770 ns | 0.0077 ns | 0.0072 ns | - |
| IROD_Foreach | 1 | 4.2435 ns | 0.0244 ns | 0.0228 ns | - |
| D_Foreach | 1 | 6.3971 ns | 0.0276 ns | 0.0258 ns | - |
| ID_Foreach | 1 | 3.3483 ns | 0.0078 ns | 0.0069 ns | - |
| FD_Foreach | 1 | 8.1952 ns | 0.0297 ns | 0.0248 ns | - |
| IFD_Foreach | 1 | 8.6295 ns | 0.0266 ns | 0.0222 ns | - |
| ROD_FindKeys | 1 | 0.4433 ns | 0.0054 ns | 0.0050 ns | - |
| IROD_FindKeys | 1 | 0.4416 ns | 0.0048 ns | 0.0045 ns | - |
| D_FindKeys | 1 | 0.4475 ns | 0.0094 ns | 0.0088 ns | - |
| ID_FindKeys | 1 | 0.4458 ns | 0.0066 ns | 0.0061 ns | - |
| FD_FindKeys | 1 | 0.4442 ns | 0.0054 ns | 0.0050 ns | - |
| IFD_FindKeys | 1 | 0.4420 ns | 0.0047 ns | 0.0044 ns | - |
| ROD_Foreach | 10 | 3.5767 ns | 0.0234 ns | 0.0219 ns | - |
| IROD_Foreach | 10 | 4.2257 ns | 0.0193 ns | 0.0162 ns | - |
| D_Foreach | 10 | 6.9439 ns | 0.0391 ns | 0.0366 ns | - |
| ID_Foreach | 10 | 3.3328 ns | 0.0168 ns | 0.0149 ns | - |
| FD_Foreach | 10 | 8.1419 ns | 0.0300 ns | 0.0266 ns | - |
| IFD_Foreach | 10 | 8.5882 ns | 0.0291 ns | 0.0272 ns | - |
| ROD_FindKeys | 10 | 0.4406 ns | 0.0068 ns | 0.0064 ns | - |
| IROD_FindKeys | 10 | 0.4456 ns | 0.0044 ns | 0.0041 ns | - |
| D_FindKeys | 10 | 0.4422 ns | 0.0041 ns | 0.0036 ns | - |
| ID_FindKeys | 10 | 0.4478 ns | 0.0052 ns | 0.0049 ns | - |
| FD_FindKeys | 10 | 0.4400 ns | 0.0053 ns | 0.0049 ns | - |
| IFD_FindKeys | 10 | 0.4460 ns | 0.0048 ns | 0.0045 ns | - |
| ROD_Foreach | 100 | 3.5923 ns | 0.0221 ns | 0.0196 ns | - |
| IROD_Foreach | 100 | 4.3478 ns | 0.0413 ns | 0.0387 ns | - |
| D_Foreach | 100 | 6.6793 ns | 0.0144 ns | 0.0134 ns | - |
| ID_Foreach | 100 | 3.2357 ns | 0.0099 ns | 0.0088 ns | - |
| FD_Foreach | 100 | 8.5819 ns | 0.0263 ns | 0.0233 ns | - |
| IFD_Foreach | 100 | 8.6202 ns | 0.0331 ns | 0.0310 ns | - |
| ROD_FindKeys | 100 | 0.4675 ns | 0.0063 ns | 0.0059 ns | - |
| IROD_FindKeys | 100 | 0.4495 ns | 0.0045 ns | 0.0042 ns | - |
| D_FindKeys | 100 | 0.4399 ns | 0.0045 ns | 0.0042 ns | - |
| ID_FindKeys | 100 | 0.4433 ns | 0.0050 ns | 0.0047 ns | - |
| FD_FindKeys | 100 | 0.4497 ns | 0.0070 ns | 0.0065 ns | - |
| IFD_FindKeys | 100 | 0.4456 ns | 0.0050 ns | 0.0042 ns | - |
| ROD_Foreach | 1000 | 3.5551 ns | 0.0170 ns | 0.0151 ns | - |
| IROD_Foreach | 1000 | 4.2293 ns | 0.0201 ns | 0.0188 ns | - |
| D_Foreach | 1000 | 6.7758 ns | 0.0911 ns | 0.0852 ns | - |
| ID_Foreach | 1000 | 3.4335 ns | 0.0173 ns | 0.0162 ns | - |
| FD_Foreach | 1000 | 8.1730 ns | 0.0354 ns | 0.0276 ns | - |
| IFD_Foreach | 1000 | 8.6196 ns | 0.0405 ns | 0.0378 ns | - |
| ROD_FindKeys | 1000 | 0.4495 ns | 0.0043 ns | 0.0040 ns | - |
| IROD_FindKeys | 1000 | 0.4467 ns | 0.0057 ns | 0.0047 ns | - |
| D_FindKeys | 1000 | 0.4462 ns | 0.0049 ns | 0.0046 ns | - |
| ID_FindKeys | 1000 | 0.4443 ns | 0.0071 ns | 0.0067 ns | - |
| FD_FindKeys | 1000 | 0.4443 ns | 0.0051 ns | 0.0047 ns | - |
| IFD_FindKeys | 1000 | 0.4454 ns | 0.0035 ns | 0.0033 ns | - |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment