Skip to content

Instantly share code, notes, and snippets.

@mrpmorris
Created April 25, 2022 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrpmorris/8b692d62e54bff035259d31d2665bc26 to your computer and use it in GitHub Desktop.
Save mrpmorris/8b692d62e54bff035259d31d2665bc26 to your computer and use it in GitHub Desktop.
// BenchmarkDotNet benchmarks to test the speed of .net framework immutable classes
// See this image for results => https://user-images.githubusercontent.com/3111981/165134368-5875560d-47ef-4627-b51f-854e0cf24d36.png
using BenchmarkDotNet.Attributes;
using System.Collections.Immutable;
namespace ConsoleApp20;
[MemoryDiagnoser]
public class BM
{
private enum Case { FirstToLast, LastToFirst };
private const int Iterations = 25_000;
private void Run<T>(Func<T> create, Case @case, Func<T, int, T> add, Func<T, int, T>? remove, int multiplier = 1)
{
while (multiplier-- > 0)
{
var instance = create();
for (int i = 1; i <= Iterations; i++)
instance = add(instance, i);
if (remove is Func<T, int, T> safeRemove)
{
if (@case == Case.FirstToLast)
for (int i = 1; i <= Iterations; i++) instance = safeRemove(instance, i);
else
for (int i = Iterations; i >= 1; i--) instance = safeRemove(instance, i);
}
}
}
// ImmutableList<T> benchmarks
[Benchmark]
public void ImmutableList_AddAllThenRemoveAtZero() =>
Run(() => ImmutableList.Create<int>(), Case.FirstToLast, (l, x) => l.Add(x), (l, x) => l = l.RemoveAt(0));
[Benchmark]
public void ImmutableList_AddAllThenRemoveFromEnd() =>
Run(() => ImmutableList.Create<int>(), Case.LastToFirst, (l, x) => l.Add(x), (l, _) => l.RemoveAt(l.Count - 1));
[Benchmark]
public void ImmutableList_AddAllThenRemoveValueFoundAtStart() =>
Run(() => ImmutableList.Create<int>(), Case.FirstToLast, (l, x) => l = l.Add(x), (l, x) => l.Remove(x));
[Benchmark]
public void ImmutableList_AddAllThenRemoveValueFoundAtEnd() =>
Run(() => ImmutableList.Create<int>(), Case.LastToFirst, (l, x) => l.Add(x), (l, x) => l.Remove(x));
[Benchmark]
public void ImmutableList_AddOnly() =>
Run(() => ImmutableList.Create<int>(), Case.FirstToLast, (l, x) => l.Add(x), null);
// List<T> benchmarks
[Benchmark]
public void List_AddAllThenRemoveAtZero() =>
Run(() => new List<int>(), Case.FirstToLast, (l, x) => { l.Add(x); return l; }, (l, _) => { l.RemoveAt(0); return l; });
[Benchmark]
public void List_AddAllThenRemoveFromEnd() =>
Run(() => new List<int>(), Case.LastToFirst, (l, x) => { l.Add(x); return l; }, (l, _) => { l.RemoveAt(l.Count - 1); return l; });
[Benchmark]
public void List_AddAllThenRemoveValueFoundAtStart() =>
Run(() => new List<int>(), Case.FirstToLast, (l, x) => { l.Add(x); return l; }, (l, x) => { l.Remove(x); return l; });
[Benchmark]
public void List_AddAllThenRemoveValueFoundAtEnd() =>
Run(() => new List<int>(), Case.LastToFirst, (l, x) => { l.Add(x); return l; }, (l, x) => { l.Remove(x); return l; });
[Benchmark]
public void List_AddOnly_100Times() =>
Run(() => new List<int>(), Case.FirstToLast, (l, x) => { l.Add(x); return l; }, null, 100);
// ImmutableArray<T> benchmarks
[Benchmark]
public void ImmutableArray_AddAllThenRemoveAtZero() =>
Run(() => ImmutableArray.Create<int>(), Case.FirstToLast, (a, x) => a.Add(x), (a, _) => a.RemoveAt(0));
[Benchmark]
public void ImmutableArray_AddAllThenRemoveFromEnd() =>
Run(() => ImmutableArray.Create<int>(), Case.LastToFirst, (a, x) => a.Add(x), (a, _) => a.RemoveAt(a.Length - 1));
[Benchmark]
public void ImmutableArray_AddAllThenRemoveValueFoundAtStart() =>
Run(() => ImmutableArray.Create<int>(), Case.FirstToLast, (a, x) => a.Add(x), (a, x) => a.Remove(x));
[Benchmark]
public void ImmutableArray_AddAllThenRemoveValueFoundAtEnd() =>
Run(() => ImmutableArray.Create<int>(), Case.LastToFirst, (a, x) => a.Add(x), (a, x) => a.Remove(x));
[Benchmark]
public void ImmutableArray_AddOnly() =>
Run(() => ImmutableArray.Create<int>(), Case.FirstToLast, (a, x) => a.Add(x), null);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment