Benchmarks added & reorganized.
This commit is contained in:
1 parent
ccf5c61dd0
commit
a216c028a0
48 files changed
+13483
-363
No files matched your search
@@ -0,0 +1,73 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum ArraySizeLimitBenchmarkType
|
||||
{
|
||||
ArraySizeLimit
|
||||
}
|
||||
|
||||
public class ArraySizeLimitBenchmarks : BaselineVsActualBenchmarkBase<ArraySizeLimitBenchmarkType>
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new ArraySizeLimitBenchmarks();
|
||||
benchmark.Setup();
|
||||
FindArraySizeLimit();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
[Params(2_147_483_605)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Benchmark(OperationsPerInvoke = 1)]
|
||||
public void Max_Allowed_Size_2_147_483_605()
|
||||
{
|
||||
long[] arr = ArrayPool<long>.Shared.Rent(TestObjectCount);
|
||||
DoNothing.With(arr);
|
||||
}
|
||||
|
||||
[Benchmark(OperationsPerInvoke = 1)]
|
||||
public static void FindArraySizeLimit()
|
||||
{
|
||||
var pool = ArrayPool<long>.Shared;
|
||||
var bufferSize = int.MaxValue / 2;
|
||||
var oldValue = 0;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.Write($"Allocating {bufferSize}...");
|
||||
var arr = pool.Rent(bufferSize);
|
||||
Console.WriteLine("success");
|
||||
pool.Return(arr);
|
||||
arr = null;
|
||||
|
||||
var nextValue = bufferSize - oldValue;
|
||||
oldValue = bufferSize;
|
||||
bufferSize = checked(bufferSize + nextValue);
|
||||
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine("error");
|
||||
var nextValue = (bufferSize - oldValue) >> 1;
|
||||
if (nextValue == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bufferSize = oldValue + nextValue;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("All done");
|
||||
throw new Exception($"Everything was successful. You can create {oldValue} byte big arrays. Exception is logged to prevent more benchmarks.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum BoolOrCompareBenchmarkType
|
||||
{
|
||||
Bool,
|
||||
Compare,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class BoolOrCompareBenchmarks : BaselineVsActualBenchmarkBase<BoolOrCompareBenchmarkType>
|
||||
{
|
||||
[Params(BoolOrCompareBenchmarkType.Bool, BoolOrCompareBenchmarkType.Compare)]
|
||||
public override BoolOrCompareBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(8)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Params(true)]
|
||||
public bool TestBool = true;
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new BoolOrCompareBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Bool();
|
||||
benchmark.Compare();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
public void Bool()
|
||||
{
|
||||
if (TestBool)
|
||||
{
|
||||
DoNothing.With(TestBool);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoNothing.With(TestBool);
|
||||
}
|
||||
}
|
||||
|
||||
public void Compare()
|
||||
{
|
||||
if (TestObjectCount >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
DoNothing.With(TestBool);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoNothing.With(TestBool);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(BoolOrCompareBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
BoolOrCompareBenchmarkType.Bool => Bool,
|
||||
BoolOrCompareBenchmarkType.Compare => Compare,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
// Ignore Spelling: Poc Structs Unboxed Funcs Comparers
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum DelegateVsComparerBenchmarkType
|
||||
{
|
||||
Comparer,
|
||||
Delegate,
|
||||
Func,
|
||||
ListOfBoxedStructs,
|
||||
ListOfClasses,
|
||||
ListOfComparers,
|
||||
ListOfDelegates,
|
||||
ListOfFuncs,
|
||||
ListOfLocalFuncs,
|
||||
ListOfStructs,
|
||||
ListOfUnboxedReadOnlyStructs,
|
||||
ListOfUnboxedStructs,
|
||||
StaticFunc,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class DelegateVsComparerBenchmarks : BaselineVsActualBenchmarkBase<DelegateVsComparerBenchmarkType>
|
||||
{
|
||||
[Params
|
||||
(
|
||||
DelegateVsComparerBenchmarkType.Delegate,
|
||||
DelegateVsComparerBenchmarkType.Func,
|
||||
DelegateVsComparerBenchmarkType.ListOfBoxedStructs,
|
||||
DelegateVsComparerBenchmarkType.ListOfClasses,
|
||||
DelegateVsComparerBenchmarkType.ListOfComparers,
|
||||
DelegateVsComparerBenchmarkType.ListOfDelegates,
|
||||
DelegateVsComparerBenchmarkType.ListOfFuncs,
|
||||
DelegateVsComparerBenchmarkType.ListOfLocalFuncs,
|
||||
DelegateVsComparerBenchmarkType.ListOfStructs,
|
||||
DelegateVsComparerBenchmarkType.ListOfUnboxedReadOnlyStructs,
|
||||
DelegateVsComparerBenchmarkType.ListOfUnboxedStructs,
|
||||
DelegateVsComparerBenchmarkType.StaticFunc
|
||||
)]
|
||||
public override DelegateVsComparerBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(DelegateVsComparerBenchmarkType.Comparer)]
|
||||
public override DelegateVsComparerBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
#region Dummy classes
|
||||
|
||||
private delegate T Compare<T>(T x, T y);
|
||||
|
||||
public readonly struct MyComparerReadOnlyStruct<T> : IComparer<T>
|
||||
{
|
||||
public int Compare(T? x, T? y) => Comparer<T>.Default.Compare(x, y);
|
||||
}
|
||||
|
||||
private struct MyComparerStruct<T> : IComparer<T>
|
||||
{
|
||||
public readonly int Compare(T? x, T? y) => Comparer<T>.Default.Compare(x, y);
|
||||
}
|
||||
|
||||
private class MyComparer : IComparer<long>
|
||||
{
|
||||
public int Compare(long x, long y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new DelegateVsComparerBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Comparer();
|
||||
benchmark.Delegate();
|
||||
benchmark.Func();
|
||||
benchmark.ListOfBoxedStructs();
|
||||
benchmark.ListOfClasses();
|
||||
benchmark.ListOfComparers();
|
||||
benchmark.ListOfDelegates();
|
||||
benchmark.ListOfFuncs();
|
||||
benchmark.ListOfLocalFuncs();
|
||||
benchmark.ListOfStructs();
|
||||
benchmark.ListOfUnboxedReadOnlyStructs();
|
||||
benchmark.ListOfUnboxedStructs();
|
||||
benchmark.StaticFunc();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
private static readonly Comparer<long> _comparer = Comparer<long>.Default;
|
||||
private IEnumerable<long>? _testObjects;
|
||||
private IEnumerable<Func<long, long, int>>? _testListOfFunctions;
|
||||
private IEnumerable<IComparer<long>>? _testListOfComparers;
|
||||
private IEnumerable<Compare<long>>? _testListOfDelegates;
|
||||
private IEnumerable<Func<long, long, int>>? _testListOfLocalFunctions;
|
||||
private IEnumerable<MyComparer>? _testListOfClasses;
|
||||
private IEnumerable<MyComparerStruct<long>>? _testListOfStructs;
|
||||
private IEnumerable<IComparer<long>>? _testListOfBoxedStructs;
|
||||
private IEnumerable<TComparer> TestListOfUnboxedStructs<TComparer, TValue>() where TComparer : IComparer<TValue>, new()
|
||||
{
|
||||
foreach (var _ in _testObjects!)
|
||||
{
|
||||
yield return new TComparer();
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<Func<long, long, int>> GetLocalFunctions(IEnumerable<long> testObjects)
|
||||
{
|
||||
static int compareFunc(long x, long y)
|
||||
{
|
||||
return (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var _ in testObjects)
|
||||
{
|
||||
yield return compareFunc;
|
||||
}
|
||||
}
|
||||
|
||||
private void TestWithComparer(IComparer<long> comparer)
|
||||
{
|
||||
var testData = _testObjects!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = comparer.Compare(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void TestWithDelegate(Compare<long> compareFunc)
|
||||
{
|
||||
var testData = _testObjects!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void TestWithFunc(Func<long, long, int> compareFunc)
|
||||
{
|
||||
var testData = _testObjects!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
public void Comparer()
|
||||
{
|
||||
TestWithComparer(_comparer);
|
||||
}
|
||||
|
||||
public void Func()
|
||||
{
|
||||
TestWithFunc((x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
public void StaticFunc()
|
||||
{
|
||||
TestWithFunc(static (x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
public void Delegate()
|
||||
{
|
||||
TestWithDelegate((x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
public void ListOfFuncs()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfFunctions!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var compareFunc = testData[itemIdx];
|
||||
_ = compareFunc(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfLocalFuncs()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfLocalFunctions!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var compareFunc = testData[itemIdx];
|
||||
_ = compareFunc(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfComparers()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfComparers!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfClasses()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfClasses!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfStructs()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfStructs!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfBoxedStructs()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfBoxedStructs!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfUnboxedStructs()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = TestListOfUnboxedStructs<MyComparerStruct<long>, long>().ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfUnboxedReadOnlyStructs()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = TestListOfUnboxedStructs<MyComparerReadOnlyStruct<long>, long>().ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfDelegates()
|
||||
{
|
||||
const long X = 2, Y = 5;
|
||||
var testData = _testListOfDelegates!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var compareDelegate = testData[itemIdx];
|
||||
_ = compareDelegate(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(DelegateVsComparerBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
DelegateVsComparerBenchmarkType.Comparer => Comparer,
|
||||
DelegateVsComparerBenchmarkType.Delegate => Delegate,
|
||||
DelegateVsComparerBenchmarkType.Func => Func,
|
||||
DelegateVsComparerBenchmarkType.ListOfBoxedStructs => ListOfBoxedStructs,
|
||||
DelegateVsComparerBenchmarkType.ListOfClasses => ListOfClasses,
|
||||
DelegateVsComparerBenchmarkType.ListOfComparers => ListOfComparers,
|
||||
DelegateVsComparerBenchmarkType.ListOfDelegates => ListOfDelegates,
|
||||
DelegateVsComparerBenchmarkType.ListOfFuncs => ListOfFuncs,
|
||||
DelegateVsComparerBenchmarkType.ListOfLocalFuncs => ListOfLocalFuncs,
|
||||
DelegateVsComparerBenchmarkType.ListOfStructs => ListOfStructs,
|
||||
DelegateVsComparerBenchmarkType.ListOfUnboxedReadOnlyStructs => ListOfUnboxedReadOnlyStructs,
|
||||
DelegateVsComparerBenchmarkType.ListOfUnboxedStructs => ListOfUnboxedStructs,
|
||||
DelegateVsComparerBenchmarkType.StaticFunc => StaticFunc,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP COMMON TEST DATA *******");
|
||||
_testObjects = Enumerable.Range(1, TestObjectCount).Select(x => (long)x);
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_testObjects = null;
|
||||
base.Cleanup();
|
||||
}
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
switch (benchmarkType)
|
||||
{
|
||||
case DelegateVsComparerBenchmarkType.ListOfBoxedStructs:
|
||||
_testListOfBoxedStructs = _testObjects!.Select(_ => (IComparer<long>)new MyComparerStruct<long>());
|
||||
break;
|
||||
case DelegateVsComparerBenchmarkType.ListOfClasses:
|
||||
_testListOfClasses = _testObjects!.Select(_ => new MyComparer());
|
||||
break;
|
||||
case DelegateVsComparerBenchmarkType.ListOfComparers:
|
||||
_testListOfComparers = _testObjects!.Select(_ => (IComparer<long>)new MyComparer());
|
||||
break;
|
||||
case DelegateVsComparerBenchmarkType.ListOfDelegates:
|
||||
_testListOfDelegates = _testObjects!.Select(_ => new Compare<long>((x, y) => new MyComparer().Compare(x, y)));
|
||||
break;
|
||||
case DelegateVsComparerBenchmarkType.ListOfFuncs:
|
||||
_testListOfFunctions = _testObjects!.Select<long, Func<long, long, int>>(static _ => new MyComparer().Compare);
|
||||
break;
|
||||
case DelegateVsComparerBenchmarkType.ListOfLocalFuncs:
|
||||
_testListOfLocalFunctions = GetLocalFunctions(_testObjects!);
|
||||
break;
|
||||
case DelegateVsComparerBenchmarkType.ListOfStructs:
|
||||
_testListOfStructs = _testObjects!.Select(_ => new MyComparerStruct<long>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using FluentAssertions;
|
||||
using Recyclable.Collections.TestData;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
|
||||
public class EqualVsContainsInConsecutiveOrderBenchmarks : IDisposable
|
||||
{
|
||||
private const int TestItemsCount = 10000;
|
||||
|
||||
private readonly IEnumerable<long> _list1 = RecyclableLongListTestData.CreateTestData(TestItemsCount).ToRecyclableList();
|
||||
private readonly IEnumerable<long> _list2 = RecyclableLongListTestData.CreateTestData(TestItemsCount).ToArray();
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void Equal()
|
||||
{
|
||||
_ = _list1.Should().Equal(_list2);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ContainsInConsecutiveOrder()
|
||||
{
|
||||
_ = _list1.Should().ContainInConsecutiveOrder(_list2);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
if (_list1 is IDisposable disposable1)
|
||||
{
|
||||
disposable1.Dispose();
|
||||
}
|
||||
|
||||
if (_list2 is IDisposable disposable2)
|
||||
{
|
||||
disposable2.Dispose();
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
#pragma warning disable CA1822 // Mark members as static
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public class GreaterOperatorVsNotEqualOperatorBenchmarks
|
||||
{
|
||||
private static readonly long _num = RecyclableDefaults.MinItemsCountForParallelization;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
Console.WriteLine($"*** We're comparing if {_num} is < 0 ***");
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void CompareWithGreater()
|
||||
{
|
||||
DoNothing.With(_num > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithGreaterEqual()
|
||||
{
|
||||
DoNothing.With(_num >= 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithNotEqual()
|
||||
{
|
||||
DoNothing.With(_num != 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithLess()
|
||||
{
|
||||
DoNothing.With(_num < 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithEqual()
|
||||
{
|
||||
DoNothing.With(_num == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
#pragma warning disable CA1822
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public class LessOperatorVsAndOperatorBenchmarks
|
||||
{
|
||||
private const int BitShift = 1 << 31;
|
||||
private static readonly Random _rnd = new(1);
|
||||
private static int _num = -Math.Abs(_rnd.Next());
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
_num = -1;
|
||||
Console.WriteLine($"*** We're comparing if {_num} is < 0 ***");
|
||||
}
|
||||
|
||||
public void Cleanup() { }
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void CompareWithLess()
|
||||
{
|
||||
DoNothing.With(_num < 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithAnd()
|
||||
{
|
||||
DoNothing.With((_num & BitShift) != 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithEqual()
|
||||
{
|
||||
DoNothing.With(_num == -1);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareToZero()
|
||||
{
|
||||
DoNothing.With(_num == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
// Ignore Spelling: Mul Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
using System.Numerics;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class ModuloBenchmarks
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new ModuloBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.AddWithFor();
|
||||
benchmark.AddWithForOptimized();
|
||||
benchmark.DividerAndModulusWithOperator();
|
||||
benchmark.MathDivRem();
|
||||
benchmark.MixedApproachWithForLoopOptimized();
|
||||
benchmark.MixedApproachWithSubtractWithStackalloc();
|
||||
benchmark.MixedApproachWithSubtractWithWhile();
|
||||
benchmark.MixedApproachWithSubtractWithWhileAsVector();
|
||||
benchmark.MixedApproachWithSubtractWithWhileWithSse2();
|
||||
benchmark.SubtractWithWhile();
|
||||
benchmark.SubtractWithWhileWithSse2();
|
||||
benchmark.XDivYMulX();
|
||||
benchmark.XDivYMulXWithLocalVar();
|
||||
}
|
||||
|
||||
private long _cutoff;
|
||||
private Vector128<long> _increment;
|
||||
private long _lastCaseIndex;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_cutoff = checked((long)BlockSize << 4);
|
||||
_increment = Vector128.Create(-BlockSize, 1L);
|
||||
_lastCaseIndex = 0;
|
||||
}
|
||||
|
||||
//[Params(123, 10, 2, int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 10, int.MaxValue / 15, int.MaxValue / 20)]
|
||||
[Params(int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 8, int.MaxValue / 10, int.MaxValue / 100)]
|
||||
//[Params(int.MaxValue / 10, int.MaxValue / 20, int.MaxValue / 100)]
|
||||
public int BlockSize { get; set; } = int.MaxValue;
|
||||
|
||||
[Params(int.MaxValue, int.MaxValue / 1000, int.MaxValue / 10000)]
|
||||
//[Params(int.MaxValue)]
|
||||
//[Params(int.MaxValue * 100L)]
|
||||
public long TestNumber { get; set; } = int.MaxValue;
|
||||
|
||||
private void CalculateDividerAndModulusWithOperator(long i)
|
||||
{
|
||||
DoNothing.With(i / BlockSize, i % BlockSize);
|
||||
}
|
||||
|
||||
private void CalculateWithMathDivRem(long i)
|
||||
{
|
||||
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
|
||||
private void CalculateWithAddWithFor(long i)
|
||||
{
|
||||
int result = 0;
|
||||
int remainder = 0;
|
||||
int blockSize = BlockSize;
|
||||
for (long iteration = 0; iteration < i; iteration++)
|
||||
{
|
||||
if (remainder > blockSize - 1)
|
||||
{
|
||||
remainder = 0;
|
||||
result++;
|
||||
}
|
||||
|
||||
remainder++;
|
||||
}
|
||||
|
||||
DoNothing.With(result, remainder);
|
||||
}
|
||||
|
||||
private void CalculateWithAddWithForOptimized(long i)
|
||||
{
|
||||
long total = 0;
|
||||
int result = 0;
|
||||
int blockSize = BlockSize;
|
||||
while (total + blockSize <= i)
|
||||
{
|
||||
total += blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing.With(result, i - total);
|
||||
}
|
||||
|
||||
private void CalculateWithXDivYMulX(long i)
|
||||
{
|
||||
DoNothing.With(i / BlockSize, i - (i / BlockSize * BlockSize));
|
||||
}
|
||||
|
||||
private void CalculateWithXDivYMulXWithLocalVar(long i)
|
||||
{
|
||||
int blockSize = BlockSize;
|
||||
int result = (int)(i / blockSize);
|
||||
DoNothing.With(result, i - (result * blockSize));
|
||||
}
|
||||
|
||||
private void CalculateWithSubtractWithWhile(long i)
|
||||
{
|
||||
int result = 0;
|
||||
long remainder = i;
|
||||
int blockSize = BlockSize;
|
||||
while (remainder >= blockSize)
|
||||
{
|
||||
remainder -= blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing.With(result, remainder);
|
||||
}
|
||||
|
||||
private void CalculateWithSubtractWithWhileWithSse2(long i)
|
||||
{
|
||||
var state = Vector128.Create(i, 0);
|
||||
int blockSize = BlockSize;
|
||||
var inc = _increment;
|
||||
while (state.GetElement(0) >= blockSize)
|
||||
{
|
||||
state = Sse2.Add(state, inc);
|
||||
}
|
||||
|
||||
DoNothing.With(state.GetElement(1), state.GetElement(0));
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithWhile(long i)
|
||||
{
|
||||
long remainder;
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing.With(Math.DivRem(i, BlockSize, out remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
int result = 0;
|
||||
int blockSize = BlockSize;
|
||||
remainder = i;
|
||||
while (remainder >= blockSize)
|
||||
{
|
||||
remainder -= blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing.With(result, remainder);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithWhileAsVector(long i)
|
||||
{
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var state = new Vector<long>(new[] { 0L, i, 0, 0 });
|
||||
var increment = new Vector<long>(new[] { 1L, -BlockSize, 0, 0 });
|
||||
int blockSize = BlockSize;
|
||||
while (state[1] >= blockSize)
|
||||
{
|
||||
state += increment;
|
||||
}
|
||||
|
||||
DoNothing.With(state[0], state[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithWhileWithSse2(long i)
|
||||
{
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var increment = _increment;
|
||||
var state = Vector128.Create(i, 0);
|
||||
int blockSize = BlockSize;
|
||||
while (state.GetElement(0) >= blockSize)
|
||||
{
|
||||
state = Sse2.Add(state, increment);
|
||||
}
|
||||
|
||||
DoNothing.With(state.GetElement(1), state.GetElement(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithStackalloc(long i)
|
||||
{
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<long> state = stackalloc long[2] { i, 0 };// Vector128.Create(BlockSize, 0);
|
||||
int blockSize = BlockSize;
|
||||
while (state[0] >= blockSize)
|
||||
{
|
||||
state[0] -= blockSize;
|
||||
state[1]++;
|
||||
}
|
||||
|
||||
DoNothing.With(state[1], state[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithForLoopOptimized(long i)
|
||||
{
|
||||
long total;
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing.With(Math.DivRem(i, BlockSize, out total), total);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = 0;
|
||||
int result = 0;
|
||||
int blockSize = BlockSize;
|
||||
while (total + blockSize <= i)
|
||||
{
|
||||
total += blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing.With(result, i - total);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void DividerAndModulusWithOperator()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateDividerAndModulusWithOperator(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void MathDivRem()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMathDivRem(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void AddWithFor()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithAddWithFor(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void AddWithForOptimized()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithAddWithForOptimized(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void XDivYMulX()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithXDivYMulX(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void XDivYMulXWithLocalVar()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithXDivYMulXWithLocalVar(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SubtractWithWhile()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithSubtractWithWhile(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SubtractWithWhileWithSse2()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithSubtractWithWhileWithSse2(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhile()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhile(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhileAsVector()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhileAsVector(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhileWithSse2()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhileWithSse2(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithStackalloc()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithStackalloc(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithForLoopOptimized()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithForLoopOptimized(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
BenchmarkDotNet=v0.13.3, OS=ubuntu 20.04
|
||||
Intel Xeon Platinum 8272CL CPU 2.60GHz, 1 CPU, 4 logical and 2 physical cores
|
||||
.NET SDK=7.0.203
|
||||
[Host] : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------------- |--------:|---------:|---------:|------:|--------:|
|
||||
| RecyclableLongList_IndexOfV1 | 2.274 s | 0.0447 s | 0.0894 s | 1.00 | 0.04 |
|
||||
| RecyclableLongList_IndexOfV2 | 2.302 s | 0.0456 s | 0.0750 s | 1.00 | 0.00 |
|
||||
| RecyclableLongList_IndexOf | 2.234 s | 0.0446 s | 0.0681 s | 0.97 | 0.05 |
|
||||
|
||||
// * Hints *
|
||||
Outliers
|
||||
RecyclableLongListPocBenchmarks.RecyclableLongList_IndexOfV2: Default -> 2 outliers were removed (2.54 s, 2.56 s)
|
||||
RecyclableLongListPocBenchmarks.RecyclableLongList_IndexOf: Default -> 1 outlier was detected (2.06 s)
|
||||
|
||||
// * Legends *
|
||||
Mean : Arithmetic mean of all measurements
|
||||
Error : Half of 99.9% confidence interval
|
||||
StdDev : Standard deviation of all measurements
|
||||
Ratio : Mean of the ratio distribution ([Current]/[Baseline])
|
||||
RatioSD : Standard deviation of the ratio distribution ([Current]/[Baseline])
|
||||
1 s : 1 Second (1 sec)
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
// Ignore Spelling: POC
|
||||
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Pooled;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public partial class RecyclableLongListBenchmarks<T> : BaselineVsActualBenchmarkBase<T>
|
||||
{
|
||||
private int[]? _testArray;
|
||||
public int[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null");
|
||||
|
||||
public RecyclableLongList<int> TestObjectsAsRecyclableLongList => _testRecyclableLongList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongList<int>)} is null");
|
||||
private RecyclableLongList<int>? _testRecyclableLongList;
|
||||
private PooledList<int>? _testPooledList;
|
||||
internal PooledList<int> TestPooledList => _testPooledList ?? throw new NullReferenceException($"Something is wrong and {nameof(PooledList<int>)} is null");
|
||||
|
||||
private static readonly MethodInfo _ensureCapacityNewFunc;
|
||||
|
||||
static RecyclableLongListBenchmarks()
|
||||
{
|
||||
_ensureCapacityNewFunc = typeof(RecyclableLongList<int>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList<int>)}");
|
||||
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP EXPECTED RESULTS DATA *******");
|
||||
_testArray = DataGenerator.EnumerateTestObjects(TestObjectCount);
|
||||
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_testArray = null;
|
||||
_testRecyclableLongList?.Dispose();
|
||||
_testRecyclableLongList = null;
|
||||
_testPooledList?.Dispose();
|
||||
_testPooledList = null;
|
||||
|
||||
base.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
//[MemoryDiagnoser]
|
||||
//public class ListVsLinkedListBenchmarks
|
||||
//{
|
||||
// [Benchmark]
|
||||
// public void RecyclableList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// using var list = new RecyclableList<object>(initialCapacity: dataCount);
|
||||
// for (int i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// [Benchmark(Baseline = true)]
|
||||
// public void RecyclableLongList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// int dataCount = TestObjectCount;
|
||||
// using var list = new RecyclableLongList<object>(BlockSize, totalItemsCount: dataCount);
|
||||
// for (int i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void List()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new List<object>(capacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (var i = 0; i < list.Count; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void LinkedList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new LinkedList<object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// _ = list.AddLast(data[i]);
|
||||
// }
|
||||
|
||||
// foreach (var node in list)
|
||||
// {
|
||||
// DoNothing(node);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableQueue()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableQueue<object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.LongCount > 0)
|
||||
// {
|
||||
// DoNothing(list.Dequeue());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void Queue()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new Queue<object>(capacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.Count > 0)
|
||||
// {
|
||||
// DoNothing(list.Dequeue());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void PriorityQueue()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new PriorityQueue<object, int>(initialCapacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i], i);
|
||||
// }
|
||||
|
||||
// while (list.Count > 0)
|
||||
// {
|
||||
// DoNothing(list.Dequeue());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableSortedList_InUpdateMode()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableSortedList<int, object>(BlockSize);
|
||||
// list.BeginUpdate();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
// }
|
||||
|
||||
// list.EndUpdate();
|
||||
|
||||
// for (var i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableSortedList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableSortedList<int, object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
// }
|
||||
|
||||
// for (var i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void SortedList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new SortedList<int, object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
// }
|
||||
|
||||
// for (var i = 0; i < list.Count; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableStack()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableStack<object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Push(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.LongCount > 0)
|
||||
// {
|
||||
// DoNothing(list.Pop());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void Stack()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new Stack<object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Push(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.Count > 0)
|
||||
// {
|
||||
// DoNothing(list.Pop());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public class RefVsInstanceMemberBenchmarks
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new RefVsInstanceMemberBenchmarks();
|
||||
benchmark.ArrayInstanceMember2();
|
||||
benchmark.ArrayInstanceMember3();
|
||||
benchmark.ArrayInstanceMember4();
|
||||
benchmark.ArrayInstanceMember5();
|
||||
benchmark.ArrayInstanceMember6();
|
||||
benchmark.ArrayInstanceMemberLocalVar5();
|
||||
benchmark.ArrayInstanceMemberLocalVar6();
|
||||
benchmark.IntInstanceMember2();
|
||||
benchmark.IntInstanceMember3();
|
||||
benchmark.IntInstanceMember4();
|
||||
benchmark.IntInstanceMember5();
|
||||
benchmark.RefToArray2();
|
||||
benchmark.RefToArray3();
|
||||
benchmark.RefToArray4();
|
||||
benchmark.RefToArray5();
|
||||
benchmark.RefToArray6();
|
||||
benchmark.RefToInt2();
|
||||
benchmark.RefToInt3();
|
||||
}
|
||||
|
||||
private readonly TestCase _testCase = new();
|
||||
private class TestCase
|
||||
{
|
||||
private int[] _items = new int[123];
|
||||
private int _count = 123;
|
||||
private static int Add(int count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get => _count;
|
||||
set => _count = value;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount2()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount3()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
_ = TestCase.Add(count);
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount4()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
_ = TestCase.Add(count);
|
||||
_ = TestCase.Add(count);
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount5()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
_ = TestCase.Add(count);
|
||||
_ = TestCase.Add(count);
|
||||
_ = TestCase.Add(count);
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember2()
|
||||
{
|
||||
_count = 234;
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember3()
|
||||
{
|
||||
_count = 234;
|
||||
_ = TestCase.Add(_count);
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember4()
|
||||
{
|
||||
_count = 234;
|
||||
_ = TestCase.Add(_count);
|
||||
_ = TestCase.Add(_count);
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember5()
|
||||
{
|
||||
_count = 234;
|
||||
_ = TestCase.Add(_count);
|
||||
_ = TestCase.Add(_count);
|
||||
_ = TestCase.Add(_count);
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray2()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray3()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray4()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray5()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray6()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArrayLocalVar5()
|
||||
{
|
||||
var items = _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArrayLocalVar6()
|
||||
{
|
||||
var items = _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray2()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray3()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray4()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray5()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray6()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt2()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount2();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt3()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount3();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt4()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount4();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt5()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount5();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void IntInstanceMember2()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember2();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void IntInstanceMember3()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember3();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void IntInstanceMember4()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember4();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void IntInstanceMember5()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember5();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray2()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray2();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray3()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray3();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray4()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray4();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray5()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray5();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray6()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray6();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember2()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray2();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember3()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray3();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember4()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray4();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember5()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray5();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember6()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray6();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMemberLocalVar5()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArrayLocalVar5();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMemberLocalVar6()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArrayLocalVar6();
|
||||
DoNothing.With(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum RoundBenchmarkType
|
||||
{
|
||||
MathFloor,
|
||||
MathRound,
|
||||
WithTypecasting,
|
||||
}
|
||||
|
||||
public class RoundBenchmarks : BaselineVsActualBenchmarkBase<RoundBenchmarkType>
|
||||
{
|
||||
[Params(RoundBenchmarkType.MathFloor)]
|
||||
public override RoundBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(RoundBenchmarkType.MathRound, RoundBenchmarkType.WithTypecasting)]
|
||||
public override RoundBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
private const double OptimalParallelSearchStep = 0.329;
|
||||
|
||||
public void RoundWithMathFloor()
|
||||
{
|
||||
DoNothing.With((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep));
|
||||
}
|
||||
|
||||
public void RoundWithMathRound()
|
||||
{
|
||||
DoNothing.With((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0));
|
||||
}
|
||||
|
||||
public void RoundWithTypeCasting()
|
||||
{
|
||||
DoNothing.With((long)(TestObjectCount * OptimalParallelSearchStep));
|
||||
}
|
||||
|
||||
protected override Action GetTestMethod(RoundBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
RoundBenchmarkType.MathFloor => RoundWithMathFloor,
|
||||
RoundBenchmarkType.MathRound => RoundWithMathRound,
|
||||
RoundBenchmarkType.WithTypecasting => RoundWithTypeCasting,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
static class RoundUpToPowerOf2Alternatives
|
||||
{
|
||||
private static readonly int[] _powersOfTwo =
|
||||
{
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
|
||||
2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576,
|
||||
2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824
|
||||
};
|
||||
|
||||
public static int BinarySearch(int value)
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw new ArgumentException("Input must be a positive integer.");
|
||||
}
|
||||
|
||||
// Find the smallest power of 2 greater than or equal to value using a lookup table
|
||||
int index = Array.BinarySearch(_powersOfTwo, value);
|
||||
if (index < 0)
|
||||
{
|
||||
// If value is not a power of 2, use the next power of 2 from the table
|
||||
index = ~index;
|
||||
}
|
||||
|
||||
return _powersOfTwo[index];
|
||||
}
|
||||
|
||||
public static int RightBitShifting(int value)
|
||||
{
|
||||
// Decrease value by 1 to handle the case where the input is already a power of 2
|
||||
value--;
|
||||
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
|
||||
return value + 1;
|
||||
}
|
||||
|
||||
public static int LeftBitShifting(int value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ensure value is a power of 2 or the next power of 2
|
||||
int result = 1;
|
||||
while (result < value)
|
||||
{
|
||||
result = checked(result << 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public enum RoundUpToPowerOf2BenchmarkType
|
||||
{
|
||||
Undefined,
|
||||
BitOperations,
|
||||
RightBitShifting,
|
||||
LeftBitShifting,
|
||||
BinarySearch,
|
||||
IsPowOf2,
|
||||
IsPowOf2_GreaterThanFirst,
|
||||
IsPowOf2_WithIf,
|
||||
IsPowOf2_GreaterEqual,
|
||||
}
|
||||
|
||||
public class RoundUpToPowerOf2vsOtherBenchmarks : BaselineVsActualBenchmarkBase<RoundUpToPowerOf2BenchmarkType>
|
||||
{
|
||||
// [Params(-850_000, 850_000)]
|
||||
[Params(-int.MaxValue, int.MaxValue)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Params(RoundUpToPowerOf2BenchmarkType.IsPowOf2)]
|
||||
public override RoundUpToPowerOf2BenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterThanFirst, RoundUpToPowerOf2BenchmarkType.IsPowOf2_WithIf, RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterEqual)]
|
||||
// [Params(RoundUpToPowerOf2BenchmarkType.RightBitShifting, RoundUpToPowerOf2BenchmarkType.LeftBitShifting, RoundUpToPowerOf2BenchmarkType.BinarySearch)]
|
||||
public override RoundUpToPowerOf2BenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
private void BitOperations()
|
||||
{
|
||||
DoNothing.With(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount));
|
||||
}
|
||||
|
||||
private void RightBitShifting()
|
||||
{
|
||||
DoNothing.With(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount));
|
||||
}
|
||||
|
||||
private void LeftBitShifting()
|
||||
{
|
||||
DoNothing.With(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount));
|
||||
}
|
||||
|
||||
private void BinarySearch()
|
||||
{
|
||||
DoNothing.With(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount));
|
||||
}
|
||||
|
||||
private void IsPowOf2()
|
||||
{
|
||||
DoNothing.With((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0);
|
||||
}
|
||||
|
||||
private void IsPowOf2_GreaterThanFirst()
|
||||
{
|
||||
DoNothing.With(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
|
||||
}
|
||||
|
||||
private void IsPowOf2_WithIf()
|
||||
{
|
||||
#pragma warning disable IDE0075 // This is intentional
|
||||
DoNothing.With(TestObjectCount > 0 ? (TestObjectCount & (TestObjectCount - 1)) == 0 : false);
|
||||
#pragma warning restore IDE0075
|
||||
}
|
||||
|
||||
private void IsPowOf2_GreaterEqual()
|
||||
{
|
||||
DoNothing.With(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(RoundUpToPowerOf2BenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
RoundUpToPowerOf2BenchmarkType.BitOperations => BitOperations,
|
||||
RoundUpToPowerOf2BenchmarkType.RightBitShifting => RightBitShifting,
|
||||
RoundUpToPowerOf2BenchmarkType.LeftBitShifting => LeftBitShifting,
|
||||
RoundUpToPowerOf2BenchmarkType.BinarySearch => BinarySearch,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2 => IsPowOf2,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterThanFirst => IsPowOf2_GreaterThanFirst,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2_WithIf => IsPowOf2_WithIf,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterEqual => IsPowOf2_GreaterEqual,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum SpanConstructorVsTypecastingBenchmarkType
|
||||
{
|
||||
Unknown,
|
||||
Constructor,
|
||||
TypeCasting,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class SpanConstructorVsTypecastingBenchmarks : BaselineVsActualBenchmarkBase<SpanConstructorVsTypecastingBenchmarkType>
|
||||
{
|
||||
private int[]? TestData { get; set; }
|
||||
|
||||
[Params(SpanConstructorVsTypecastingBenchmarkType.TypeCasting)]
|
||||
public override SpanConstructorVsTypecastingBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(SpanConstructorVsTypecastingBenchmarkType.Constructor)]
|
||||
public override SpanConstructorVsTypecastingBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(8)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new SpanConstructorVsTypecastingBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Constructor();
|
||||
benchmark.TypeCasting();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
public void Constructor()
|
||||
{
|
||||
ReadOnlySpan<int> span = new(TestData);
|
||||
DoNothing.With(span);
|
||||
}
|
||||
|
||||
public void TypeCasting()
|
||||
{
|
||||
ReadOnlySpan<int> span = TestData;
|
||||
DoNothing.With(span);
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
TestData = new int[TestObjectCount];
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(SpanConstructorVsTypecastingBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
SpanConstructorVsTypecastingBenchmarkType.Constructor => Constructor,
|
||||
SpanConstructorVsTypecastingBenchmarkType.TypeCasting => TypeCasting,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum SpanVsArrayBenchmarkType
|
||||
{
|
||||
ArrayGetWithVar,
|
||||
ArrayGetWithField,
|
||||
SpanGet,
|
||||
ArraySetWithVar,
|
||||
ArraySetWithField,
|
||||
SpanSet
|
||||
}
|
||||
|
||||
public class SpanVsArrayBenchmarks : DataDrivenBenchmarksBase<SpanVsArrayBenchmarkType>
|
||||
{
|
||||
// [Params(SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet)]
|
||||
// [Params(SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet)]
|
||||
[Params
|
||||
(
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithField, SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet
|
||||
)]
|
||||
public override SpanVsArrayBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(SpanVsArrayBenchmarkType.ArrayGetWithField)]
|
||||
// [Params(SpanVsArrayBenchmarkType.ArraySetWithField)]
|
||||
public override SpanVsArrayBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
protected override Action GetTestMethod(SpanVsArrayBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithVar => ArrayGetWithVar,
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithField => ArrayGetWithField,
|
||||
SpanVsArrayBenchmarkType.SpanGet => SpanGet,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithVar => ArraySetWithVar,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithField => ArraySetWithField,
|
||||
SpanVsArrayBenchmarkType.SpanSet => SpanSet,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
public void ArrayGetWithVar()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void ArrayGetWithField()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing.With(_testObjects![i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void SpanGet()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
Span<int> data = new(_testObjects, 0, dataCount);
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void ArraySetWithVar()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public void ArraySetWithField()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
_testObjects![i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public void SpanSet()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
Span<int> data = new(_testObjects, 0, dataCount);
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,59 @@
|
||||
// Ignore Spelling: Poc
|
||||
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class TaskRunVsTaskFactoryStartNewBenchmarks
|
||||
{
|
||||
public int NumberOfTasks = 100;
|
||||
private static readonly TaskFactory _taskPool = new();
|
||||
|
||||
[Benchmark]
|
||||
public void OwnTaskFactory()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
_ = _taskPool.StartNew(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskRun()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
_ = Task.Run(() => { });
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void TaskFactoryStartNew()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
_ = Task.Factory.StartNew(() => { });
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskConstructor()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
new Task(() => { }).Start();
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskConstructorWithKnownScheduler()
|
||||
{
|
||||
TaskScheduler scheduler = TaskScheduler.Current;
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
new Task(() => { }).Start(scheduler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user