Skip to content

Commit

Permalink
benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
2A5F committed Dec 7, 2023
1 parent 9599e02 commit ec5d9de
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Benchmark/Benchmark.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0;net6.0;net7.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\BetterCollections\BetterCollections.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.11" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.11" />
</ItemGroup>

</Project>
77 changes: 77 additions & 0 deletions Benchmark/BenchmarkFlatHashMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using BenchmarkDotNet.Attributes;
using BetterCollections;

namespace Benchmark;

[MemoryDiagnoser]
[RPlotExporter]
public class BenchmarkFlatHashMap_Add1000
{
[Benchmark]
public FlatHashMap<int, int> FlatHashMap()
{
var map = new FlatHashMap<int, int>();
for (var i = 0; i < 1000; i++)
{
map.Add(i, i);
}
return map;
}

[Benchmark(Baseline = true)]
public Dictionary<int, int> Dictionary()
{
var map = new Dictionary<int, int>();
for (var i = 0; i < 1000; i++)
{
map.Add(i, i);
}
return map;
}
}

[MemoryDiagnoser]
[RPlotExporter]
public class BenchmarkFlatHashMap_Get1000
{
private FlatHashMap<int, int> flatHashMap = new();
private Dictionary<int, int> dictionary = new();

[GlobalSetup]
public void Setup()
{
flatHashMap = new FlatHashMap<int, int>();
for (var i = 0; i < 1000; i++)
{
flatHashMap.Add(i, i);
}

dictionary = new Dictionary<int, int>();
for (var i = 0; i < 1000; i++)
{
dictionary.Add(i, i);
}
}

[Benchmark]
public int FlatHashMap()
{
var a = 0;
for (var i = 0; i < 1000; i++)
{
a += flatHashMap[i];
}
return a;
}

[Benchmark(Baseline = true)]
public int Dictionary()
{
var a = 0;
for (var i = 0; i < 1000; i++)
{
a += dictionary[i];
}
return a;
}
}
3 changes: 3 additions & 0 deletions Benchmark/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
6 changes: 6 additions & 0 deletions BetterCollections.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterCollections", "Better
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{95336675-5EC6-470C-A4A9-A0D44B28C987}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "Benchmark\Benchmark.csproj", "{745D3703-B07D-4B10-95D5-A96AD07E6BE9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -18,5 +20,9 @@ Global
{95336675-5EC6-470C-A4A9-A0D44B28C987}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95336675-5EC6-470C-A4A9-A0D44B28C987}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95336675-5EC6-470C-A4A9-A0D44B28C987}.Release|Any CPU.Build.0 = Release|Any CPU
{745D3703-B07D-4B10-95D5-A96AD07E6BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{745D3703-B07D-4B10-95D5-A96AD07E6BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{745D3703-B07D-4B10-95D5-A96AD07E6BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{745D3703-B07D-4B10-95D5-A96AD07E6BE9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
12 changes: 12 additions & 0 deletions BetterCollections/Exceptions/UnexpectedConcurrentException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace BetterCollections.Exceptions;

public class UnexpectedConcurrentException : Exception
{
public UnexpectedConcurrentException() : this(
"A concurrent call occurred on a container that does not allow concurrency, and the internal state may have been corrupted") { }

public UnexpectedConcurrentException(string message) : base(message) { }
public UnexpectedConcurrentException(string message, Exception inner) : base(message, inner) { }
}
45 changes: 45 additions & 0 deletions BetterCollections/Misc/IRefGet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace BetterCollections.Misc;

public interface IGetter<out T, S>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Get(in S source);
}

public readonly struct IdentityGetter<T> : IGetter<T, T>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Get(in T source) => source;
}

public readonly struct KeyValueGetter<K, V> : IGetter<KeyValuePair<K, V>, (K Key, V Value)>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public KeyValuePair<K, V> Get(in (K Key, V Value) source)
=> new(source.Key, source.Value);
}

public readonly struct KeyGetter<K, V> : IGetter<K, (K Key, V Value)>, IGetter<K, KeyValuePair<K, V>>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public K Get(in (K Key, V Value) source)
=> source.Key;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public K Get(in KeyValuePair<K, V> source)
=> source.Key;
}

public readonly struct ValueGetter<K, V> : IGetter<V, (K Key, V Value)>, IGetter<V, KeyValuePair<K, V>>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public V Get(in (K Key, V Value) source)
=> source.Value;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public V Get(in KeyValuePair<K, V> source)
=> source.Value;
}
14 changes: 14 additions & 0 deletions BetterCollections/Misc/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,18 @@ public static string ToBinaryString(this ulong value)
return Regex.Replace(a, ".{8}(?!$)", "$0_");
#endif
}

/// <summary>
/// Evaluate whether a given integral value is a power of 2.
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsPow2(long value) => (value & (value - 1)) == 0 && value > 0;

/// <summary>
/// Evaluate whether a given integral value is a power of 2.
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsPow2(ulong value) => (value & (value - 1)) == 0 && value > 0;
}

0 comments on commit ec5d9de

Please sign in to comment.