List<T> compatibility code moved to Recyclable.Collections.Compatibility.List package. Cleanup.

This commit is contained in:
mlemanczyk committed 2023-10-21 17:29:53 +02:00
1 parent ec69b1c406
commit 203b13268f
61 files changed
+1634 -4375

No files matched your search

@@ -1,18 +1,21 @@
using BenchmarkDotNet.Attributes;
// Ignore Spelling: Poc
using BenchmarkDotNet.Attributes;
using Collections.Benchmarks.Core;
using System.Buffers;
namespace Recyclable.Collections.Benchmarks.POC
{
public enum ArraySizeLimitPocBenchmarkType
public enum ArraySizeLimitBenchmarkType
{
ArraySizeLimit
}
public class ArraySizeLimitPocBenchmarks : PocBenchmarkBase<ArraySizeLimitPocBenchmarkType>
public class ArraySizeLimitBenchmarks : BaselineVsActualBenchmarkBase<ArraySizeLimitBenchmarkType>
{
public static void Run()
{
var benchmark = new ArraySizeLimitPocBenchmarks();
var benchmark = new ArraySizeLimitBenchmarks();
benchmark.Setup();
FindArraySizeLimit();
benchmark.Cleanup();
@@ -25,7 +28,7 @@ namespace Recyclable.Collections.Benchmarks.POC
public void Max_Allowed_Size_2_147_483_605()
{
long[] arr = ArrayPool<long>.Shared.Rent(TestObjectCount);
DoNothing(arr);
DoNothing.With(arr);
}
[Benchmark(OperationsPerInvoke = 1)]
@@ -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),
};
}
}
@@ -1,63 +0,0 @@
using BenchmarkDotNet.Attributes;
namespace Recyclable.Collections.Benchmarks.POC
{
public enum BoolOrComparePocBenchmarkType
{
Bool,
Compare,
}
[MemoryDiagnoser]
public class BoolOrComparePocBenchmarks : PocBenchmarkBase<BoolOrComparePocBenchmarkType>
{
[Params(BoolOrComparePocBenchmarkType.Bool, BoolOrComparePocBenchmarkType.Compare)]
public override BoolOrComparePocBenchmarkType 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 BoolOrComparePocBenchmarks();
benchmark.Setup();
benchmark.Bool();
benchmark.Compare();
benchmark.Cleanup();
}
public void Bool()
{
if (TestBool)
{
DoNothing(TestBool);
}
else
{
DoNothing(TestBool);
}
}
public void Compare()
{
if (TestObjectCount >= RecyclableDefaults.MinPooledArrayLength)
{
DoNothing(TestBool);
}
else
{
DoNothing(TestBool);
}
}
protected override Action? GetTestMethod(BoolOrComparePocBenchmarkType benchmarkType) => benchmarkType switch
{
BoolOrComparePocBenchmarkType.Bool => Bool,
BoolOrComparePocBenchmarkType.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;
}
}
}
}
@@ -1,346 +0,0 @@
using BenchmarkDotNet.Attributes;
namespace Recyclable.Collections.Benchmarks.POC
{
public enum DelegateVsComparerPocBenchmarkType
{
Comparer,
Delegate,
Func,
ListOfBoxedStructs,
ListOfClasses,
ListOfComparers,
ListOfDelegates,
ListOfFuncs,
ListOfLocalFuncs,
ListOfStructs,
ListOfUnboxedReadOnlyStructs,
ListOfUnboxedStructs,
StaticFunc,
}
[MemoryDiagnoser]
public class DelegateVsComparerPocBenchmarks : PocBenchmarkBase<DelegateVsComparerPocBenchmarkType>
{
[Params
(
DelegateVsComparerPocBenchmarkType.Delegate,
DelegateVsComparerPocBenchmarkType.Func,
DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs,
DelegateVsComparerPocBenchmarkType.ListOfClasses,
DelegateVsComparerPocBenchmarkType.ListOfComparers,
DelegateVsComparerPocBenchmarkType.ListOfDelegates,
DelegateVsComparerPocBenchmarkType.ListOfFuncs,
DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs,
DelegateVsComparerPocBenchmarkType.ListOfStructs,
DelegateVsComparerPocBenchmarkType.ListOfUnboxedReadOnlyStructs,
DelegateVsComparerPocBenchmarkType.ListOfUnboxedStructs,
DelegateVsComparerPocBenchmarkType.StaticFunc
)]
public override DelegateVsComparerPocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
[Params(DelegateVsComparerPocBenchmarkType.Comparer)]
public override DelegateVsComparerPocBenchmarkType 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 DelegateVsComparerPocBenchmarks();
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(DelegateVsComparerPocBenchmarkType benchmarkType) => benchmarkType switch
{
DelegateVsComparerPocBenchmarkType.Comparer => Comparer,
DelegateVsComparerPocBenchmarkType.Delegate => Delegate,
DelegateVsComparerPocBenchmarkType.Func => Func,
DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs => ListOfBoxedStructs,
DelegateVsComparerPocBenchmarkType.ListOfClasses => ListOfClasses,
DelegateVsComparerPocBenchmarkType.ListOfComparers => ListOfComparers,
DelegateVsComparerPocBenchmarkType.ListOfDelegates => ListOfDelegates,
DelegateVsComparerPocBenchmarkType.ListOfFuncs => ListOfFuncs,
DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs => ListOfLocalFuncs,
DelegateVsComparerPocBenchmarkType.ListOfStructs => ListOfStructs,
DelegateVsComparerPocBenchmarkType.ListOfUnboxedReadOnlyStructs => ListOfUnboxedReadOnlyStructs,
DelegateVsComparerPocBenchmarkType.ListOfUnboxedStructs => ListOfUnboxedStructs,
DelegateVsComparerPocBenchmarkType.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 DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs:
_testListOfBoxedStructs = _testObjects!.Select(_ => (IComparer<long>)new MyComparerStruct<long>());
break;
case DelegateVsComparerPocBenchmarkType.ListOfClasses:
_testListOfClasses = _testObjects!.Select(_ => new MyComparer());
break;
case DelegateVsComparerPocBenchmarkType.ListOfComparers:
_testListOfComparers = _testObjects!.Select(_ => (IComparer<long>)new MyComparer());
break;
case DelegateVsComparerPocBenchmarkType.ListOfDelegates:
_testListOfDelegates = _testObjects!.Select(_ => new Compare<long>((x, y) => new MyComparer().Compare(x, y)));
break;
case DelegateVsComparerPocBenchmarkType.ListOfFuncs:
_testListOfFunctions = _testObjects!.Select<long, Func<long, long, int>>(static _ => new MyComparer().Compare);
break;
case DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs:
_testListOfLocalFunctions = GetLocalFunctions(_testObjects!);
break;
case DelegateVsComparerPocBenchmarkType.ListOfStructs:
_testListOfStructs = _testObjects!.Select(_ => new MyComparerStruct<long>());
break;
}
}
}
}
@@ -2,7 +2,7 @@
using BenchmarkDotNet.Attributes;
using FluentAssertions;
using Recyclable.CollectionsTests;
using Recyclable.Collections.TestData;
namespace Recyclable.Collections.Benchmarks.POC
{
@@ -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);
}
}
}
@@ -1,57 +0,0 @@
using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
#pragma warning disable CA1822
namespace Recyclable.Collections.Benchmarks.POC
{
public class GreaterOperatorVsDoesntEqualOperatorBenchmarks
{
private static readonly long num = RecyclableDefaults.MinItemsCountForParallelization;
public void Setup()
{
Console.WriteLine($"*** We're comparing if {num} is < 0 ***");
}
public void Cleanup() { }
#pragma warning disable RCS1163, IDE0060
[MethodImpl(MethodImplOptions.NoInlining)]
private static void DoNothing<T>(T item)
{
}
#pragma warning restore RCS1163
[Benchmark(Baseline = true)]
public void CompareWithGreater()
{
DoNothing(num > 0 ? 1 : 0);
}
[Benchmark]
public void CompareWithGreaterEqual()
{
DoNothing(num >= 0 ? 1 : 0);
}
[Benchmark]
public void CompareWithDoesntEqual()
{
DoNothing(num != 0 ? 1 : 0);
}
[Benchmark]
public void CompareWithLess()
{
DoNothing(num < 0 ? 1 : 0);
}
[Benchmark]
public void CompareWithEqual()
{
DoNothing(num == 0 ? 0 : 1);
}
}
}
@@ -1,7 +1,7 @@
// Ignore Spelling: Poc
using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
using Collections.Benchmarks.Core;
#pragma warning disable CA1822
@@ -21,36 +21,28 @@ namespace Recyclable.Collections.Benchmarks.POC
public void Cleanup() { }
#pragma warning disable RCS1163, IDE0060
[MethodImpl(MethodImplOptions.NoInlining)]
private static void DoNothing<T>(T item)
{
}
#pragma warning restore RCS1163
[Benchmark(Baseline = true)]
public void CompareWithLess()
{
DoNothing(_num < 0);
DoNothing.With(_num < 0);
}
[Benchmark]
public void CompareWithAnd()
{
DoNothing((_num & BitShift) != 0);
DoNothing.With((_num & BitShift) != 0);
}
[Benchmark]
public void CompareWithEqual()
{
DoNothing(_num == -1);
DoNothing.With(_num == -1);
}
[Benchmark]
public void CompareToZero()
{
DoNothing(_num == 0);
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);
}
}
}
}
@@ -1,376 +0,0 @@
using BenchmarkDotNet.Attributes;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#pragma warning disable xUnit1026, RCS1163, IDE0060
namespace Recyclable.Collections.Benchmarks.POC
{
[MemoryDiagnoser]
public class ModuloPocBenchmarks
{
public static void Run()
{
var benchmark = new ModuloPocBenchmarks();
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;
}
private static void DoNothing<T>(T result, T remainder, [CallerMemberName] string? callerName = null)
{
//Console.WriteLine($"{callerName}: result = {result}, remainder = {remainder}");
}
//[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(i / BlockSize, i % BlockSize);
}
private void CalculateWithMathDivRem(long i)
{
DoNothing(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(result, remainder);
}
private void CalculateWithAddWithForOptimized(long i)
{
long total = 0;
int result = 0;
int blockSize = BlockSize;
while (total + blockSize <= i)
{
total += blockSize;
result++;
}
DoNothing(result, i - total);
}
private void CalculateWithXDivYMulX(long i)
{
DoNothing(i / BlockSize, i - (i / BlockSize * BlockSize));
}
private void CalculateWithXDivYMulXWithLocalVar(long i)
{
int blockSize = BlockSize;
int result = (int)(i / blockSize);
DoNothing(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(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(state.GetElement(1), state.GetElement(0));
}
private void CalculateWithMixedApproachWithSubtractWithWhile(long i)
{
long remainder;
if (i >= _cutoff)
{
DoNothing(Math.DivRem(i, BlockSize, out remainder), remainder);
}
else
{
int result = 0;
int blockSize = BlockSize;
remainder = i;
while (remainder >= blockSize)
{
remainder -= blockSize;
result++;
}
DoNothing(result, remainder);
}
}
private void CalculateWithMixedApproachWithSubtractWithWhileAsVector(long i)
{
if (i >= _cutoff)
{
DoNothing(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(state[0], state[1]);
}
}
private void CalculateWithMixedApproachWithSubtractWithWhileWithSse2(long i)
{
if (i >= _cutoff)
{
DoNothing(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(state.GetElement(1), state.GetElement(0));
}
}
private void CalculateWithMixedApproachWithSubtractWithStackalloc(long i)
{
if (i >= _cutoff)
{
DoNothing(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(state[1], state[0]);
}
}
private void CalculateWithMixedApproachWithForLoopOptimized(long i)
{
long total;
if (i >= _cutoff)
{
DoNothing(Math.DivRem(i, BlockSize, out total), total);
}
else
{
total = 0;
int result = 0;
int blockSize = BlockSize;
while (total + blockSize <= i)
{
total += blockSize;
result++;
}
DoNothing(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);
}
}
}
}
@@ -1,142 +0,0 @@
using BenchmarkDotNet.Attributes;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace Recyclable.Collections.Benchmarks.POC
{
public abstract class PocBenchmarkBase<TBenchmarkType>
{
public virtual TBenchmarkType? DataType { get; set; }
public virtual TBenchmarkType? BaseDataType { get; set; }
private Action? _testMethod;
protected Action TestMethod
{
get => _testMethod ?? throw new OperationCanceledException("Skip - No actual defined");
set => _testMethod = value;
}
private Action? _baselineMethod;
protected Action BaselineMethod
{
get => _baselineMethod ?? throw new OperationCanceledException("Skip - No baseline defined");
set => _baselineMethod = value;
}
[Benchmark(Baseline = true)]
public void Baseline() => BaselineMethod.Invoke();
[Benchmark]
public void Actual() => TestMethod.Invoke();
// 0 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524_288
// 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912
// 1073741824 2147483648
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)]
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)]
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 100_000_000)]
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 850_000 - 1, 1_000_000, RecyclableDefaults.MaxPooledBlockSize)]
// [Params(1_000_000, 10_000_000, 100_000_000, 1_000_000_000)]
// [Params(1, 10, 64, 128, 192, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144)]
// [Params(524_288, 786_432, 1_048_576)]
// [Params(262_144, 393_216, 524_288)]
// [Params(850_000_000)]
// [Params(100_000_000)]
// [Params(RecyclableDefaults.MinItemsCountForParallelization)]
// [Params(127)]
// [Params(16)]
// [Params(10, 15, 128)]
// [Params(1)]
// [Params(RecyclableDefaults.MaxPooledBlockSize)]
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 10_000_000, 33_554_432, 50_000_000, 100_000_000)]
// *** [Params(RecyclableDefaults.MinPooledArrayLength - 3, RecyclableDefaults.MinPooledArrayLength - 2, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 2, RecyclableDefaults.MinPooledArrayLength + 3)]
[Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
// *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
// [Params(256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
// [Params(RecyclableDefaults.MinItemsCountForParallelization, 1_048_576, 2_097_152, 4_194_304, 8_388_608, 16_777_216, 33_554_432, RecyclableDefaults.MaxPooledBlockSize)]
// *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 64, 70, 80, 90, 100, 127, 128)]
// [Params(1, 10, 1024, 10240, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinItemsCountForParallelization)]
// [Params(RecyclableDefaults.MinItemsCountForParallelization * 3)]
// [Params(1_048_576)]
public virtual int TestObjectCount { get; set; } = 0; //8_192;//131_072; //1; //33_554_432; //524_288; //131_072;
public virtual int TestObjectCountForSlowMethods { get; private set; }
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200)]
// [Params(10, 20, 50, 100)]
// [Params(1, 10)]
public int Divider = 10;
//public int BlockSize = 1_048_576;//int.MaxValue - 1;
public int BlockSize { get; private set; }
public byte BlockSizePow2BitShift => checked((byte)(31 - BitOperations.LeadingZeroCount((uint)BlockSize)));
[MethodImpl(MethodImplOptions.NoInlining)]
protected static void DoNothing<T>(in T item)
{
_ = item;
}
protected static Exception CreateUnknownBenchmarkTypeException<T>(T benchmarkType)
{
return new InvalidOperationException($"******* UNKNOWN BENCHMARK TYPE {{{benchmarkType}}} *******");
}
protected static Exception CreateMethodNotFoundException(in string methodName, in string? className)
{
return new MethodAccessException($"******* METHOD {{{methodName}}} NOT FOUND IN CLASS {{{className}}} *******");
}
protected virtual void PrepareData<T>(T benchmarkType) { }
protected virtual Action? GetTestMethod(TBenchmarkType? benchmarkType) => null;
[GlobalCleanup]
public virtual void Cleanup()
{
_baselineMethod = null;
_testMethod = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
}
[GlobalSetup]
public virtual void Setup()
{
Console.WriteLine($"******* SETTING UP TEST CASE FOR BENCHMARK {{{DataType}}} *******");
TestObjectCountForSlowMethods = (TestObjectCount / 2) + 1;
BlockSize = TestObjectCount switch
{
0 => 1,
> 0 and <= 10_240 => TestObjectCount,
_ => TestObjectCount / Divider > 0 ? TestObjectCount / Divider : TestObjectCount
};
if (BlockSize > 0)
{
BlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)BlockSize));
}
Console.WriteLine($"******* BaseDataType = {BaseDataType}; default = {default(TBenchmarkType)} *******");
if (!EqualityComparer<TBenchmarkType>.Default.Equals(BaseDataType, default))
{
Console.WriteLine("******* SETTING UP BASELINE DATA *******");
PrepareData(BaseDataType);
_baselineMethod = GetTestMethod(BaseDataType);
}
//~ We don't want to prepare data if baseline data is the same is benchmark data.
//~ One would override another - waste of time & resources.
if (!EqualityComparer<TBenchmarkType>.Default.Equals(BaseDataType, DataType))
{
Console.WriteLine("******* SETTING UP TEST CASE DATA *******");
//~ If BaseDataType == null, then we'll come here only if DataType != null.
PrepareData(DataType!);
_testMethod = GetTestMethod(DataType);
}
Console.WriteLine("******* DATA PREPARED *******");
}
}
}
@@ -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();
// }
//}
}
@@ -1,47 +0,0 @@
using System.Reflection;
using BenchmarkDotNet.Attributes;
using Collections.Pooled;
using Recyclable.Collections.Benchmarks.Core;
namespace Recyclable.Collections.Benchmarks.POC
{
[MemoryDiagnoser]
public partial class RecyclableLongListPocBenchmarks<T> : PocBenchmarkBase<T>
{
private long[]? _testArray;
public long[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null");
public RecyclableLongList<long> TestObjectsAsRecyclableLongList => _testRecyclableLongList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongList<long>)} is null");
private RecyclableLongList<long>? _testRecyclableLongList;
private PooledList<long>? _testPooledList;
internal PooledList<long> TestPooledList => _testPooledList ?? throw new NullReferenceException($"Something is wrong and {nameof(PooledList<long>)} is null");
private static readonly MethodInfo _ensureCapacityNewFunc;
static RecyclableLongListPocBenchmarks()
{
_ensureCapacityNewFunc = typeof(RecyclableLongList<long>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic)
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList<long>)}");
}
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();
}
}
}
@@ -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);
}
}
}
@@ -1,364 +0,0 @@
using BenchmarkDotNet.Attributes;
#pragma warning disable RCS1085
namespace Recyclable.Collections.Benchmarks.POC
{
public class RefVsInstanceMemberPocBenchmarks
{
public static void Run()
{
var benchmark = new RefVsInstanceMemberPocBenchmarks();
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 static void DoNothing(int count)
{
_ = count;
}
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(count);
}
[Benchmark]
public void RefToInt3()
{
var count = _testCase.GetCountAsRefCount3();
DoNothing(count);
}
[Benchmark]
public void RefToInt4()
{
var count = _testCase.GetCountAsRefCount4();
DoNothing(count);
}
[Benchmark]
public void RefToInt5()
{
var count = _testCase.GetCountAsRefCount5();
DoNothing(count);
}
[Benchmark(Baseline = true)]
public void IntInstanceMember2()
{
var count = _testCase.GetCountAsInstanceMember2();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void IntInstanceMember3()
{
var count = _testCase.GetCountAsInstanceMember3();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void IntInstanceMember4()
{
var count = _testCase.GetCountAsInstanceMember4();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void IntInstanceMember5()
{
var count = _testCase.GetCountAsInstanceMember5();
DoNothing(count);
}
[Benchmark]
public void RefToArray2()
{
var count = _testCase.GetLengthAsRefArray2();
DoNothing(count);
}
[Benchmark]
public void RefToArray3()
{
var count = _testCase.GetLengthAsRefArray3();
DoNothing(count);
}
[Benchmark]
public void RefToArray4()
{
var count = _testCase.GetLengthAsRefArray4();
DoNothing(count);
}
[Benchmark]
public void RefToArray5()
{
var count = _testCase.GetLengthAsRefArray5();
DoNothing(count);
}
[Benchmark]
public void RefToArray6()
{
var count = _testCase.GetLengthAsRefArray6();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMember2()
{
var count = _testCase.GetLengthAsArray2();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMember3()
{
var count = _testCase.GetLengthAsArray3();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMember4()
{
var count = _testCase.GetLengthAsArray4();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMember5()
{
var count = _testCase.GetLengthAsArray5();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMember6()
{
var count = _testCase.GetLengthAsArray6();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMemberLocalVar5()
{
var count = _testCase.GetLengthAsArrayLocalVar5();
DoNothing(count);
}
[Benchmark(Baseline = false)]
public void ArrayInstanceMemberLocalVar6()
{
var count = _testCase.GetLengthAsArrayLocalVar6();
DoNothing(count);
}
}
}
@@ -1,6 +1,7 @@
// Ignore Spelling: Poc
using BenchmarkDotNet.Attributes;
using Collections.Benchmarks.Core;
namespace Recyclable.Collections.Benchmarks.POC
{
@@ -11,7 +12,7 @@ namespace Recyclable.Collections.Benchmarks.POC
WithTypecasting,
}
public class RoundBenchmarks : PocBenchmarkBase<RoundBenchmarkType>
public class RoundBenchmarks : BaselineVsActualBenchmarkBase<RoundBenchmarkType>
{
[Params(RoundBenchmarkType.MathFloor)]
public override RoundBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
@@ -23,17 +24,17 @@ namespace Recyclable.Collections.Benchmarks.POC
public void RoundWithMathFloor()
{
DoNothing((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep));
DoNothing.With((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep));
}
public void RoundWithMathRound()
{
DoNothing((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0));
DoNothing.With((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0));
}
public void RoundWithTypeCasting()
{
DoNothing((long)(TestObjectCount * OptimalParallelSearchStep));
DoNothing.With((long)(TestObjectCount * OptimalParallelSearchStep));
}
protected override Action GetTestMethod(RoundBenchmarkType benchmarkType) => benchmarkType switch
@@ -1,10 +1,13 @@
// Ignore Spelling: Poc
using BenchmarkDotNet.Attributes;
using Collections.Benchmarks.Core;
namespace Recyclable.Collections.Benchmarks.POC
{
static class RoundUpToPowerOf2Alternatives
{
private static readonly int[] PowersOfTwo =
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,
@@ -19,14 +22,14 @@ namespace Recyclable.Collections.Benchmarks.POC
}
// Find the smallest power of 2 greater than or equal to value using a lookup table
int index = Array.BinarySearch(PowersOfTwo, value);
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];
return _powersOfTwo[index];
}
public static int RightBitShifting(int value)
@@ -74,7 +77,7 @@ namespace Recyclable.Collections.Benchmarks.POC
IsPowOf2_GreaterEqual,
}
public class RoundUpToPowerOf2vsOtherBenchmarks : PocBenchmarkBase<RoundUpToPowerOf2BenchmarkType>
public class RoundUpToPowerOf2vsOtherBenchmarks : BaselineVsActualBenchmarkBase<RoundUpToPowerOf2BenchmarkType>
{
// [Params(-850_000, 850_000)]
[Params(-int.MaxValue, int.MaxValue)]
@@ -89,42 +92,44 @@ namespace Recyclable.Collections.Benchmarks.POC
private void BitOperations()
{
DoNothing(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount));
DoNothing.With(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount));
}
private void RightBitShifting()
{
DoNothing(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount));
DoNothing.With(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount));
}
private void LeftBitShifting()
{
DoNothing(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount));
DoNothing.With(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount));
}
private void BinarySearch()
{
DoNothing(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount));
DoNothing.With(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount));
}
private void IsPowOf2()
{
DoNothing((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0);
DoNothing.With((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0);
}
private void IsPowOf2_GreaterThanFirst()
{
DoNothing(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
DoNothing.With(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
}
private void IsPowOf2_WithIf()
{
DoNothing(TestObjectCount > 0 ? (TestObjectCount & (TestObjectCount - 1)) == 0 : false);
#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(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
DoNothing.With(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
}
protected override Action? GetTestMethod(RoundUpToPowerOf2BenchmarkType benchmarkType) => benchmarkType switch
@@ -1,64 +0,0 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
namespace Recyclable.Collections.Benchmarks.POC
{
public enum SpanConstructorVsTypecastingPocBenchmarkType
{
Unknown,
Constructor,
TypeCasting,
}
[MemoryDiagnoser]
public class SpanConstructorVsTypecastingPocBenchmarks : PocBenchmarkBase<SpanConstructorVsTypecastingPocBenchmarkType>
{
private int[]? TestData { get; set; }
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
private void DoNothing(ReadOnlySpan<int> span) { }
[Params(SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting)]
public override SpanConstructorVsTypecastingPocBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
[Params(SpanConstructorVsTypecastingPocBenchmarkType.Constructor)]
public override SpanConstructorVsTypecastingPocBenchmarkType 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 SpanConstructorVsTypecastingPocBenchmarks();
benchmark.Setup();
benchmark.Constructor();
benchmark.TypeCasting();
benchmark.Cleanup();
}
public void Constructor()
{
ReadOnlySpan<int> span = new(TestData);
DoNothing(span);
}
public void TypeCasting()
{
ReadOnlySpan<int> span = TestData;
DoNothing(span);
}
public override void Setup()
{
TestData = new int[TestObjectCount];
base.Setup();
}
protected override Action? GetTestMethod(SpanConstructorVsTypecastingPocBenchmarkType benchmarkType) => benchmarkType switch
{
SpanConstructorVsTypecastingPocBenchmarkType.Constructor => Constructor,
SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting => TypeCasting,
_ => throw CreateUnknownBenchmarkTypeException(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),
};
}
}
@@ -1,6 +1,7 @@
// Ignore Spelling: Poc
using BenchmarkDotNet.Attributes;
using Collections.Benchmarks.Core;
namespace Recyclable.Collections.Benchmarks.POC
{
@@ -14,7 +15,7 @@ namespace Recyclable.Collections.Benchmarks.POC
SpanSet
}
public class SpanVsArrayBenchmarks : RecyclableBenchmarkBase<SpanVsArrayBenchmarkType>
public class SpanVsArrayBenchmarks : DataDrivenBenchmarksBase<SpanVsArrayBenchmarkType>
{
// [Params(SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet)]
// [Params(SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet)]
@@ -46,7 +47,7 @@ namespace Recyclable.Collections.Benchmarks.POC
var dataCount = TestObjectCount;
for (int i = 0; i < dataCount; i++)
{
DoNothing(data[i]);
DoNothing.With(data[i]);
}
}
@@ -55,7 +56,7 @@ namespace Recyclable.Collections.Benchmarks.POC
var dataCount = TestObjectCount;
for (int i = 0; i < dataCount; i++)
{
DoNothing(_testObjects![i]);
DoNothing.With(_testObjects![i]);
}
}
@@ -65,7 +66,7 @@ namespace Recyclable.Collections.Benchmarks.POC
Span<int> data = new(_testObjects, 0, dataCount);
for (int i = 0; i < dataCount; i++)
{
DoNothing(data[i]);
DoNothing.With(data[i]);
}
}