Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime issue 14477 more immutable benchmarks #2306

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ public Dictionary<T, T> Dictionary()
collection.TryAdd(uniqueValues[i], uniqueValues[i]);
return collection;
}

[Benchmark]
public SortedDictionary<T, T> SortedDictionary()
{
var collection = new SortedDictionary<T, T>();
var uniqueValues = _uniqueValues;
for (int i = 0; i < uniqueValues.Length; i++)
collection.TryAdd(uniqueValues[i], uniqueValues[i]);
return collection;
}

[Benchmark]
public SortedList<T, T> SortedList()
{
var collection = new SortedList<T, T>();
var uniqueValues = _uniqueValues;
for (int i = 0; i < uniqueValues.Length; i++)
collection.TryAdd(uniqueValues[i], uniqueValues[i]);
return collection;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't end up adding TryAdd benchmarks for the immutable collections here because they just use the TryAdd extension which does not work for them.

#endif

[Benchmark]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Extensions;
using MicroBenchmarks;

namespace System.Collections
{
[BenchmarkCategory(Categories.Libraries, Categories.Collections, Categories.GenericCollections)]
[GenericTypeArguments(typeof(int), typeof(int))] // value type
[GenericTypeArguments(typeof(string), typeof(string))] // reference type
public class ContainsValueFalse<TKey, TValue>
{
private TValue[] _notFound;
private Dictionary<TKey, TValue> _source;

private Dictionary<TKey, TValue> _dictionary;
private SortedList<TKey, TValue> _sortedList;
private SortedDictionary<TKey, TValue> _sortedDictionary;
private ImmutableDictionary<TKey, TValue> _immutableDictionary;
private ImmutableSortedDictionary<TKey, TValue> _immutableSortedDictionary;

[Params(Utils.DefaultCollectionSize)]
public int Size;

[GlobalSetup]
public void Setup()
{
var values = ValuesGenerator.ArrayOfUniqueValues<TValue>(Size * 2);
_notFound = values.Take(Size).ToArray();

_source = values.Skip(Size).Take(Size).ToDictionary(item => (TKey)(object)item, item => item);
_dictionary = new Dictionary<TKey, TValue>(_source);
_sortedList = new SortedList<TKey, TValue>(_source);
_sortedDictionary = new SortedDictionary<TKey, TValue>(_source);
_immutableDictionary = Immutable.ImmutableDictionary.CreateRange<TKey, TValue>(_source);
_immutableSortedDictionary = Immutable.ImmutableSortedDictionary.CreateRange<TKey, TValue>(_source);
}

[Benchmark]
public bool Dictionary()
{
bool result = default;
var collection = _dictionary;
var notFound = _notFound;
for (int i = 0; i < notFound.Length; i++)
result ^= collection.ContainsValue(notFound[i]);
return result;
}

[Benchmark]
public bool SortedList()
{
bool result = default;
var collection = _sortedList;
var notFound = _notFound;
for (int i = 0; i < notFound.Length; i++)
result ^= collection.ContainsValue(notFound[i]);
return result;
}

[Benchmark]
public bool SortedDictionary()
{
bool result = default;
var collection = _sortedDictionary;
var notFound = _notFound;
for (int i = 0; i < notFound.Length; i++)
result ^= collection.ContainsValue(notFound[i]);
return result;
}

[Benchmark]
public bool ImmutableDictionary()
{
bool result = default;
var collection = _immutableDictionary;
var notFound = _notFound;
for (int i = 0; i < notFound.Length; i++)
result ^= collection.ContainsValue(notFound[i]);
return result;
}

[Benchmark]
public bool ImmutableSortedDictionary()
{
bool result = default;
var collection = _immutableSortedDictionary;
var notFound = _notFound;
for (int i = 0; i < notFound.Length; i++)
result ^= collection.ContainsValue(notFound[i]);
return result;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Extensions;
using MicroBenchmarks;

namespace System.Collections
{
[BenchmarkCategory(Categories.Libraries, Categories.Collections, Categories.GenericCollections)]
[GenericTypeArguments(typeof(int), typeof(int))] // value type
[GenericTypeArguments(typeof(string), typeof(string))] // reference type
public class ContainsValueTrue<TKey, TValue>
{
private TValue[] _found;
private Dictionary<TKey, TValue> _source;

private Dictionary<TKey, TValue> _dictionary;
private SortedList<TKey, TValue> _sortedList;
private SortedDictionary<TKey, TValue> _sortedDictionary;
private ImmutableDictionary<TKey, TValue> _immutableDictionary;
private ImmutableSortedDictionary<TKey, TValue> _immutableSortedDictionary;

[Params(Utils.DefaultCollectionSize)]
public int Size;

[GlobalSetup]
public void Setup()
{
_found = ValuesGenerator.ArrayOfUniqueValues<TValue>(Size);
_source = _found.ToDictionary(item => (TKey)(object)item, item => item);
_dictionary = new Dictionary<TKey, TValue>(_source);
_sortedList = new SortedList<TKey, TValue>(_source);
_sortedDictionary = new SortedDictionary<TKey, TValue>(_source);
_immutableDictionary = Immutable.ImmutableDictionary.CreateRange<TKey, TValue>(_source);
_immutableSortedDictionary = Immutable.ImmutableSortedDictionary.CreateRange<TKey, TValue>(_source);
}

[Benchmark]
public bool Dictionary()
{
bool result = default;
var collection = _dictionary;
var found = _found;
for (int i = 0; i < found.Length; i++)
result ^= collection.ContainsValue(found[i]);
return result;
}

[Benchmark]
public bool SortedList()
{
bool result = default;
var collection = _sortedList;
var found = _found;
for (int i = 0; i < found.Length; i++)
result ^= collection.ContainsValue(found[i]);
return result;
}

[Benchmark]
public bool SortedDictionary()
{
bool result = default;
var collection = _sortedDictionary;
var found = _found;
for (int i = 0; i < found.Length; i++)
result ^= collection.ContainsValue(found[i]);
return result;
}

[Benchmark]
public bool ImmutableDictionary()
{
bool result = default;
var collection = _immutableDictionary;
var found = _found;
for (int i = 0; i < found.Length; i++)
result ^= collection.ContainsValue(found[i]);
return result;
}

[Benchmark]
public bool ImmutableSortedDictionary()
{
bool result = default;
var collection = _immutableSortedDictionary;
var found = _found;
for (int i = 0; i < found.Length; i++)
result ^= collection.ContainsValue(found[i]);
return result;
}
}
}
11 changes: 11 additions & 0 deletions src/benchmarks/micro/libraries/System.Collections/CopyTo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class CopyTo<T>
private T[] _array;
private List<T> _list;
private ImmutableArray<T> _immutablearray;
private ImmutableList<T> _immutableList;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All collection shave the CopyTo method (e. g. dictionaries, sets, etc) but since the original file only went with lists and arrays I also took that approach. Happy to add the rest of the collections if desired

private T[] _destination;

[GlobalSetup(Targets = new[] { nameof(Array), nameof(Span), nameof(ReadOnlySpan), nameof(Memory), nameof(ReadOnlyMemory) })]
Expand Down Expand Up @@ -68,5 +69,15 @@ public void SetupImmutableArray()

[Benchmark]
public void ImmutableArray() => _immutablearray.CopyTo(_destination);

[GlobalSetup(Target = nameof(ImmutableList))]
public void SetupImmutableList()
{
_immutableList = Immutable.ImmutableList.CreateRange(ValuesGenerator.ArrayOfUniqueValues<T>(Size));
_destination = new T[Size];
}

[Benchmark]
public void ImmutableList() => _immutableList.CopyTo(_destination);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using BenchmarkDotNet.Extensions;
using MicroBenchmarks;
using System.Collections.Generic;
using System.Collections.Immutable;

namespace System.Collections
{
Expand Down Expand Up @@ -157,5 +158,125 @@ public Queue<T> Queue()
}
return queue;
}

[Benchmark]
public ImmutableArray<T> ImmutableArray()
{
ImmutableArray<T> immutableArray = ImmutableArray<T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableArray = immutableArray.Add(uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableArray = immutableArray.Remove(uniqueKey);
}
return immutableArray;
}

[Benchmark]
public ImmutableList<T> ImmutableList()
{
ImmutableList<T> immutableList = ImmutableList<T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableList = immutableList.Add(uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableList = immutableList.Remove(uniqueKey);
}
return immutableList;
}

[Benchmark]
public ImmutableHashSet<T> ImmutableHashSet()
{
ImmutableHashSet<T> immutableHashSet = ImmutableHashSet<T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableHashSet = immutableHashSet.Add(uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableHashSet = immutableHashSet.Remove(uniqueKey);
}
return immutableHashSet;
}

[Benchmark]
public ImmutableSortedSet<T> ImmutableSortedSet()
{
ImmutableSortedSet<T> immutableSortedSet = ImmutableSortedSet<T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableSortedSet = immutableSortedSet.Add(uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableSortedSet = immutableSortedSet.Remove(uniqueKey);
}
return immutableSortedSet;
}

[Benchmark]
public ImmutableDictionary<T, T> ImmutableDictionary()
{
ImmutableDictionary<T, T> immutableDictionary = ImmutableDictionary<T, T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableDictionary = immutableDictionary.Add(uniqueKey, uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableDictionary = immutableDictionary.Remove(uniqueKey);
}
return immutableDictionary;
}

[Benchmark]
public ImmutableSortedDictionary<T, T> ImmutableSortedDictionary()
{
ImmutableSortedDictionary<T, T> immutableSortedDictionary = ImmutableSortedDictionary<T, T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableSortedDictionary = immutableSortedDictionary.Add(uniqueKey, uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableSortedDictionary = immutableSortedDictionary.Remove(uniqueKey);
}
return immutableSortedDictionary;
}

[Benchmark]
public ImmutableStack<T> ImmutableStack()
{
ImmutableStack<T> immutableStack = ImmutableStack<T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableStack = immutableStack.Push(uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableStack = immutableStack.Pop();
}
return immutableStack;
}

[Benchmark]
public ImmutableQueue<T> ImmutableQueue()
{
ImmutableQueue<T> immutableQueue = ImmutableQueue<T>.Empty;
foreach (T uniqueKey in _keys)
{
immutableQueue = immutableQueue.Enqueue(uniqueKey);
}
foreach (T uniqueKey in _keys)
{
immutableQueue = immutableQueue.Dequeue();
}
return immutableQueue;
}
}
}
Loading