List<T> compatibility code moved to Recyclable.Collections.Compatibility.List package. Cleanup.
This commit is contained in:
1 parent
ec69b1c406
commit
203b13268f
61 files changed
+1634
-4375
No files matched your search
+1
-1
@@ -3,7 +3,7 @@ The project & source code is free for educational & personal use. **Any
|
||||
|
||||
# Donation requirements for a life-time, commercial use
|
||||
* Commercial license is paid one time.
|
||||
* It can be obtained by donaiting $10 for each developer seat, using the link provided below. If you hire 2 developers, you need to donate $20 for a life-time, commercial use of this package.
|
||||
* It can be obtained by donating $10 for each developer seat, using the link provided below. If you hire 2 developers, you need to donate $20 for a life-time, commercial use of this package.
|
||||
* Your license stays with you, if your developer moves somewhere else.
|
||||
|
||||
# Link for donations
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
@@ -0,0 +1,6 @@
|
||||
################################################################################
|
||||
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
|
||||
################################################################################
|
||||
|
||||
/bin
|
||||
/obj
|
||||
@@ -1,65 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.BinarySearch(list, data[i]));
|
||||
DoNothing(Array.BinarySearch(list, data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.BinarySearch(data[i]));
|
||||
DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.BinarySearch(data[i]));
|
||||
DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.BinarySearch(data[i]));
|
||||
DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_BinarySearch_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.BinarySearch(data[i]));
|
||||
// DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -9,7 +11,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[i]) >= 0);
|
||||
DoNothing.With(Array.IndexOf(list, data[i]) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +22,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
DoNothing.With(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
DoNothing.With(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
DoNothing.With(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
DoNothing.With(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -9,7 +11,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +22,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
DoNothing(Array.ConvertAll(list, static (item) => (long) item));
|
||||
}
|
||||
|
||||
public void List_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
DoNothing(list.ConvertAll(static (item) => (long)item));
|
||||
}
|
||||
|
||||
public void PooledList_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
using var converted = list.ConvertAll(static (item) => (long)item);
|
||||
DoNothing(converted);
|
||||
}
|
||||
|
||||
public void RecyclableList_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
using RecyclableList<long> converted = list.ConvertAll(static (item) => (long)item);
|
||||
DoNothing(converted);
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_ConvertAll()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// using RecyclableList<long> converted = list.ConvertAll(static (item) => (long)item);
|
||||
// DoNothing(converted);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,37 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Count()
|
||||
{
|
||||
var data = TestObjects;
|
||||
DoNothing(data.Length);
|
||||
DoNothing.With(data.Length);
|
||||
}
|
||||
|
||||
public void List_Count()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
DoNothing(data.Count);
|
||||
DoNothing.With(data.Count);
|
||||
}
|
||||
|
||||
public void PooledList_Count()
|
||||
{
|
||||
var data = TestObjectsAsPooledList;
|
||||
DoNothing(data.Count);
|
||||
DoNothing.With(data.Count);
|
||||
}
|
||||
|
||||
public void RecyclableList_Count()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
DoNothing(data.Count);
|
||||
DoNothing.With(data.Count);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Count()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
DoNothing(data.Count);
|
||||
DoNothing.With(data.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Collections.Pooled;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
#pragma warning disable CA1822, CA1825
|
||||
|
||||
@@ -9,31 +10,31 @@ namespace Recyclable.Collections.Benchmarks
|
||||
public void Array_Create()
|
||||
{
|
||||
var list = new int[0];
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void List_Create()
|
||||
{
|
||||
var list = new List<int>();
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void PooledList_Create()
|
||||
{
|
||||
using var list = new PooledList<int>(ClearMode.Auto);
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void RecyclableList_Create()
|
||||
{
|
||||
using var list = new RecyclableList<int>();
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Create()
|
||||
{
|
||||
using var list = new RecyclableLongList<int>();
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Collections.Pooled;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
@@ -7,31 +8,31 @@ namespace Recyclable.Collections.Benchmarks
|
||||
public void Array_Create_WithCapacity()
|
||||
{
|
||||
var data = new int[TestObjectCount];
|
||||
DoNothing(data);
|
||||
DoNothing.With(data);
|
||||
}
|
||||
|
||||
public void List_Create_WithCapacity()
|
||||
{
|
||||
var list = new List<int>(TestObjectCount);
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void PooledList_Create_WithCapacity()
|
||||
{
|
||||
using var list = new PooledList<int>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void RecyclableList_Create_WithCapacity()
|
||||
{
|
||||
using var list = new RecyclableList<int>(TestObjectCount);
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Create_WithCapacity()
|
||||
{
|
||||
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize, initialCapacity: TestObjectCount);
|
||||
DoNothing(list);
|
||||
DoNothing.With(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.Exists(list, (x) => x == data[i]));
|
||||
DoNothing(Array.Exists(list, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Exists((x) => x == data[i]));
|
||||
DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Exists((x) => x == data[i]));
|
||||
DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Exists((x) => x == data[i]));
|
||||
DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_Exists_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.Exists((x) => x == data[i]));
|
||||
// DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.FindAll(list, (item) => item == data[i]));
|
||||
DoNothing(Array.FindAll(list, (item) => item == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindAll((item) => item == data[i]));
|
||||
DoNothing(list.FindAll((item) => item == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
var temp = list.FindAll((item) => item == data[i]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
|
||||
temp = list.FindAll((item) => item == data[^(i + 1)]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
var temp = list.FindAll((item) => item == data[i]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
|
||||
temp = list.FindAll((item) => item == data[^(i + 1)]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_FindAll_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// var temp = list.FindAll((item) => item == data[i]);
|
||||
// DoNothing(temp);
|
||||
// temp.Dispose();
|
||||
|
||||
// temp = list.FindAll((item) => item == data[^(i + 1)]);
|
||||
// DoNothing(temp);
|
||||
// temp.Dispose();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_FindLastIndex_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
// Console.WriteLine($"data.Length={data.Length}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
DoNothing(Array.FindLastIndex(list, 0, (x) => x == data[i]));
|
||||
DoNothing(Array.FindLastIndex(list, 0, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_FindLastIndex_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
// Console.WriteLine($"data.Length={data.Length}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[i]));
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_FindLastIndex_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[i]));
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_FindLastIndex_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.FindLastIndex(0, (x) => x == data[i]));
|
||||
// DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_FindLast_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.FindLast(list, (x) => x == data[i]));
|
||||
DoNothing(Array.FindLast(list, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_FindLast_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindLast((x) => x == data[i]));
|
||||
DoNothing(list.FindLast((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_FindLast_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindLast((x) => x == data[i]));
|
||||
DoNothing(list.FindLast((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_FindLast_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.FindLast((x) => x == data[i]));
|
||||
// DoNothing(list.FindLast((x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Find_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.Find(list, (x) => x == data[i]));
|
||||
DoNothing(Array.Find(list, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_Find_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Find((x) => x == data[i]));
|
||||
DoNothing(list.Find((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Find_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Find((x) => x == data[i]));
|
||||
DoNothing(list.Find((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_Find_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.Find((x) => x == data[i]));
|
||||
// DoNothing(list.Find((x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -6,7 +8,7 @@
|
||||
{
|
||||
foreach (var item in TestObjects)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +16,7 @@
|
||||
{
|
||||
foreach (var item in TestObjects)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +24,7 @@
|
||||
{
|
||||
foreach (var item in TestObjectsAsList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +32,7 @@
|
||||
{
|
||||
foreach (var item in TestObjectsAsList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +40,7 @@
|
||||
{
|
||||
foreach (var item in TestObjectsAsPooledList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +48,7 @@
|
||||
{
|
||||
foreach (var item in TestObjectsAsPooledList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,15 +56,15 @@
|
||||
{
|
||||
foreach (var item in TestObjectsAsRecyclableList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_VersionedForEach()
|
||||
{
|
||||
foreach (var item in (IRecyclableVersionedList<long>)TestObjectsAsRecyclableList)
|
||||
foreach (var item in (IRecyclableVersionedList<int>)TestObjectsAsRecyclableList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,15 +72,15 @@
|
||||
{
|
||||
foreach (var item in TestObjectsAsRecyclableLongList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_VersionedForEach()
|
||||
{
|
||||
foreach (var item in (IRecyclableVersionedLongList<long>)TestObjectsAsRecyclableLongList)
|
||||
foreach (var item in (IRecyclableVersionedLongList<int>)TestObjectsAsRecyclableLongList)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -8,7 +10,7 @@
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +20,7 @@
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +30,7 @@
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +40,7 @@
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +50,7 @@
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
DoNothing.With(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@
|
||||
var memoryBlock = new Span<int>(memoryBlocks[blockIndex], 0, blockSize);
|
||||
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
DoNothing.With(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +75,7 @@
|
||||
var memoryBlock = new Span<int>(memoryBlocks[nextItemBlockIndex], 0, data.NextItemIndex);
|
||||
for (var itemIndex = 0; itemIndex < memoryBlock.Length; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
DoNothing.With(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +92,7 @@
|
||||
var memoryBlock = memoryBlocks[blockIndex];
|
||||
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
DoNothing.With(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +102,7 @@
|
||||
blockSize = data.NextItemIndex;
|
||||
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
DoNothing.With(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,7 +112,7 @@
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
foreach (var item in data)
|
||||
{
|
||||
DoNothing(item);
|
||||
DoNothing.With(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +133,7 @@
|
||||
var memoryBlock = memoryBlocks[0];
|
||||
while (blockIndex < nextItemBlockIndex)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
DoNothing.With(memoryBlock[itemIndex]);
|
||||
if (itemIndex + 1 < blockSize)
|
||||
{
|
||||
itemIndex++;
|
||||
@@ -150,7 +152,7 @@
|
||||
blockSize = data.NextItemIndex;
|
||||
while (itemIndex < blockSize)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex++]);
|
||||
DoNothing.With(memoryBlock[itemIndex++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -9,8 +11,8 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[i]));
|
||||
DoNothing(Array.IndexOf(list, data[^(i + 1)]));
|
||||
DoNothing.With(Array.IndexOf(list, data[i]));
|
||||
DoNothing.With(Array.IndexOf(list, data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +23,8 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +35,8 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +47,8 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +59,8 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +71,8 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.LongIndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.LongIndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -9,7 +11,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[i]));
|
||||
DoNothing.With(Array.IndexOf(list, data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +22,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing.With(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.LongIndexOf(data[i]));
|
||||
DoNothing.With(list.LongIndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
@@ -9,7 +11,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[^(i + 1)]));
|
||||
DoNothing.With(Array.IndexOf(list, data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +22,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.LongIndexOf(data[^(i + 1)]));
|
||||
DoNothing.With(list.LongIndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_LongCount()
|
||||
{
|
||||
var data = TestObjects;
|
||||
DoNothing(data.LongLength);
|
||||
DoNothing.With(data.LongLength);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_LongCount()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
DoNothing(data.LongCount);
|
||||
DoNothing.With(data.LongCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +1,115 @@
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public enum RecyclableCollectionsBenchmarkType
|
||||
public partial class RecyclableCollectionsBenchmarks : DataDrivenBenchmarksBase<CollectionsBenchmarksSource>
|
||||
{
|
||||
Unknown, Add_WithCapacity, Add, AddRange_WithCapacity, AddRangeWhenSourceIsArray, AddRangeWhenSourceIsIEnumerable,
|
||||
AddRangeWhenSourceIsIList, AddRangeWhenSourceIsList, AddRangeWhenSourceIsSameType, BinarySearch_BestAndWorstCases,
|
||||
Contains_FirstItems, Contains_LastItems, ConvertAll, Count, Create_WithCapacity, Create, Exists_BestAndWorstCases,
|
||||
Find_BestAndWorstCases, FindAll_BestAndWorstCases, FindLast_BestAndWorstCases, FindLastIndex_BestAndWorstCases,
|
||||
ForEach, GetItem, IndexOf_BestAndWorstCases,IndexOf_FirstItems, IndexOf_LastItems, LongCount,
|
||||
Remove_FirstItems, Remove_LastItems, RemoveAt_FirstItems, RemoveAt_LastItems,
|
||||
SetItem, VersionedForEach
|
||||
}
|
||||
protected override string GetTestMethodName(CollectionsBenchmarksSource benchmarkType) => TestCase switch
|
||||
{
|
||||
CollectionsBenchmarkType.AddRangeWhenSourceIsSameType => $"{benchmarkType}_AddRangeWhenSourceIs{benchmarkType}",
|
||||
_ => $"{benchmarkType}_{TestCase}"
|
||||
};
|
||||
|
||||
public partial class RecyclableCollectionsBenchmarks : RecyclableBenchmarkBase<RecyclableCollectionsBenchmarkSource>
|
||||
{
|
||||
public RecyclableCollectionsBenchmarks()
|
||||
{
|
||||
TestObjectCount = 1;
|
||||
//BaseDataType = RecyclableCollectionsBenchmarkSource.List;
|
||||
DataType = RecyclableCollectionsBenchmarkSource.RecyclableList;
|
||||
//BaseDataType = RecyclableCollectionsBenchmarksSource.List;
|
||||
DataType = CollectionsBenchmarksSource.RecyclableList;
|
||||
}
|
||||
|
||||
[Params
|
||||
(
|
||||
RecyclableCollectionsBenchmarkType.Add_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.Add,
|
||||
RecyclableCollectionsBenchmarkType.AddRange_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsArray,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsList,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType,
|
||||
RecyclableCollectionsBenchmarkType.BinarySearch_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.Contains_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.Contains_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.ConvertAll,
|
||||
RecyclableCollectionsBenchmarkType.Count,
|
||||
RecyclableCollectionsBenchmarkType.Create_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.Create,
|
||||
RecyclableCollectionsBenchmarkType.Exists_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.Find_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.FindAll_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.FindLast_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.FindLastIndex_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.ForEach,
|
||||
RecyclableCollectionsBenchmarkType.GetItem,
|
||||
RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.IndexOf_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.IndexOf_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.LongCount,
|
||||
RecyclableCollectionsBenchmarkType.Remove_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.Remove_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.RemoveAt_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.RemoveAt_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.SetItem,
|
||||
RecyclableCollectionsBenchmarkType.VersionedForEach
|
||||
)]
|
||||
// 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
|
||||
|
||||
public RecyclableCollectionsBenchmarkType TestCase { get; set; } = RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases;
|
||||
// [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(16_384)]
|
||||
// [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 override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Params
|
||||
(
|
||||
RecyclableCollectionsBenchmarkSource.List
|
||||
CollectionsBenchmarksSource.Array,
|
||||
CollectionsBenchmarksSource.List,
|
||||
CollectionsBenchmarksSource.PooledList,
|
||||
CollectionsBenchmarksSource.RecyclableList,
|
||||
CollectionsBenchmarksSource.RecyclableLongList
|
||||
)]
|
||||
public override RecyclableCollectionsBenchmarkSource BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
public override CollectionsBenchmarksSource DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params
|
||||
(
|
||||
RecyclableCollectionsBenchmarkSource.Array,
|
||||
RecyclableCollectionsBenchmarkSource.List,
|
||||
RecyclableCollectionsBenchmarkSource.PooledList,
|
||||
RecyclableCollectionsBenchmarkSource.RecyclableList,
|
||||
RecyclableCollectionsBenchmarkSource.RecyclableLongList
|
||||
CollectionsBenchmarkType.Add_WithCapacity,
|
||||
CollectionsBenchmarkType.Add,
|
||||
CollectionsBenchmarkType.AddRange_WithCapacity,
|
||||
CollectionsBenchmarkType.AddRangeWhenSourceIsArray,
|
||||
CollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable,
|
||||
CollectionsBenchmarkType.AddRangeWhenSourceIsIList,
|
||||
CollectionsBenchmarkType.AddRangeWhenSourceIsList,
|
||||
CollectionsBenchmarkType.AddRangeWhenSourceIsSameType,
|
||||
CollectionsBenchmarkType.BinarySearch_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.Contains_FirstItems,
|
||||
CollectionsBenchmarkType.Contains_LastItems,
|
||||
CollectionsBenchmarkType.ConvertAll,
|
||||
CollectionsBenchmarkType.Count,
|
||||
CollectionsBenchmarkType.Create_WithCapacity,
|
||||
CollectionsBenchmarkType.Create,
|
||||
CollectionsBenchmarkType.Exists_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.Find_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.FindAll_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.FindLast_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.FindLastIndex_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.ForEach,
|
||||
CollectionsBenchmarkType.GetItem,
|
||||
CollectionsBenchmarkType.IndexOf_BestAndWorstCases,
|
||||
CollectionsBenchmarkType.IndexOf_FirstItems,
|
||||
CollectionsBenchmarkType.IndexOf_LastItems,
|
||||
CollectionsBenchmarkType.LongCount,
|
||||
CollectionsBenchmarkType.Remove_FirstItems,
|
||||
CollectionsBenchmarkType.Remove_LastItems,
|
||||
CollectionsBenchmarkType.RemoveAt_FirstItems,
|
||||
CollectionsBenchmarkType.RemoveAt_LastItems,
|
||||
CollectionsBenchmarkType.SetItem,
|
||||
CollectionsBenchmarkType.VersionedForEach
|
||||
)]
|
||||
public override RecyclableCollectionsBenchmarkSource DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
protected override Action? GetTestMethod(RecyclableCollectionsBenchmarkSource benchmarkType)
|
||||
=> TestCase switch
|
||||
{
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType => (Action?)GetType().GetMethod($"{benchmarkType}_AddRangeWhenSourceIs{benchmarkType}", BindingFlags.Instance | BindingFlags.Public)?.CreateDelegate(typeof(Action), this),
|
||||
_ => (Action?) GetType().GetMethod($"{benchmarkType}_{TestCase}", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)?.CreateDelegate(typeof(Action), this) ?? throw new InvalidOperationException($"Method {benchmarkType}_{TestCase} not found in class {GetType().FullName}")
|
||||
};
|
||||
public virtual CollectionsBenchmarkType TestCase { get; set; }
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
switch(TestCase)
|
||||
{
|
||||
case RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList:
|
||||
PrepareData(RecyclableCollectionsBenchmarkSource.RecyclableLongList);
|
||||
case CollectionsBenchmarkType.AddRangeWhenSourceIsIList:
|
||||
PrepareData(CollectionsBenchmarksSource.RecyclableLongList);
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType:
|
||||
PrepareData(RecyclableCollectionsBenchmarkSource.RecyclableList);
|
||||
case CollectionsBenchmarkType.AddRangeWhenSourceIsSameType:
|
||||
PrepareData(CollectionsBenchmarksSource.RecyclableList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Collections.Pooled;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
@@ -11,7 +12,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +23,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +34,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Collections.Pooled;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
@@ -11,7 +12,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +23,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +34,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
DoNothing.With(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks.Core
|
||||
{
|
||||
public static class DataGenerator
|
||||
{
|
||||
public static long[] EnumerateTestObjects(long testObjectCount)
|
||||
{
|
||||
var result = new long[testObjectCount];
|
||||
Console.WriteLine("******* TEST DATA ARRAY CREATED *******");
|
||||
|
||||
Span<long> resultSpan = result;
|
||||
for (int i = 0; i < testObjectCount; i++)
|
||||
{
|
||||
resultSpan[i] = i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-57
@@ -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 *******");
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+36
-92
@@ -1,104 +1,48 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
// Ignore Spelling: POC
|
||||
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Pooled;
|
||||
using Recyclable.Collections.Benchmarks.Core;
|
||||
using Recyclable.Collections.Benchmarks.POC;
|
||||
using Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum RecyclableCollectionsBenchmarkSource
|
||||
{
|
||||
Unknown,
|
||||
Array,
|
||||
List,
|
||||
PooledList,
|
||||
RecyclableList,
|
||||
RecyclableLongList,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class RecyclableBenchmarkBase<TBenchmarkType> : PocBenchmarkBase<TBenchmarkType>
|
||||
public partial class RecyclableLongListBenchmarks<T> : BaselineVsActualBenchmarkBase<T>
|
||||
{
|
||||
protected long[]? _testObjects;
|
||||
protected long[] TestObjects => _testObjects ?? throw new NullReferenceException("Something is wrong and the field is not initialized");
|
||||
private int[]? _testArray;
|
||||
public int[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null");
|
||||
|
||||
protected List<long>? _testObjectsAsList;
|
||||
protected List<long> TestObjectsAsList => _testObjectsAsList ?? throw new NullReferenceException("Something went wrong and the field is not initialized");
|
||||
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");
|
||||
|
||||
protected PooledList<long>? _testObjectsAsPooledList;
|
||||
public PooledList<long> TestObjectsAsPooledList => _testObjectsAsPooledList ?? throw new NullReferenceException("Something is wrong and the field is not initialized");
|
||||
protected RecyclableList<long>? _testObjectsAsRecyclableList;
|
||||
protected RecyclableList<long> TestObjectsAsRecyclableList => _testObjectsAsRecyclableList ?? throw new NullReferenceException("Something is wrong and the field is not initialized");
|
||||
protected RecyclableLongList<long>? _testObjectsAsRecyclableLongList;
|
||||
protected RecyclableLongList<long> TestObjectsAsRecyclableLongList => _testObjectsAsRecyclableLongList ?? throw new NullReferenceException("Something is wrong and the field is not initialized");
|
||||
protected IEnumerable<long> TestObjectsAsIEnumerable
|
||||
private static readonly MethodInfo _ensureCapacityNewFunc;
|
||||
|
||||
static RecyclableLongListBenchmarks()
|
||||
{
|
||||
get
|
||||
{
|
||||
for (long i = 0; i < TestObjectCount; i++)
|
||||
{
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
_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()
|
||||
{
|
||||
PrepareData(RecyclableCollectionsBenchmarkSource.Array);
|
||||
Console.WriteLine("******* SETTING UP EXPECTED RESULTS DATA *******");
|
||||
_testArray = DataGenerator.EnumerateTestObjects(TestObjectCount);
|
||||
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
Console.WriteLine($"******* PREPARING DATA FOR {benchmarkType} *******");
|
||||
switch (benchmarkType)
|
||||
{
|
||||
case RecyclableCollectionsBenchmarkSource.Unknown:
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkSource.Array:
|
||||
_testObjects ??= DataGenerator.EnumerateTestObjects(TestObjectCount);
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkSource.List:
|
||||
_testObjectsAsList ??= TestObjects.ToList();
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkSource.PooledList:
|
||||
_testObjectsAsPooledList ??= new PooledList<long>(TestObjects, ClearMode.Auto);
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkSource.RecyclableList:
|
||||
_testObjectsAsRecyclableList ??= new(TestObjects, initialCapacity: TestObjectCount);
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkSource.RecyclableLongList:
|
||||
_testObjectsAsRecyclableLongList ??= new(TestObjects, BlockSize, initialCapacity: base.TestObjectCount);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw CreateUnknownBenchmarkTypeException(benchmarkType);
|
||||
}
|
||||
|
||||
base.PrepareData(benchmarkType);
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
Console.WriteLine("******* GLOBAL CLEANUP *******");
|
||||
// Enable this if item type is changed to reference type
|
||||
//if (_testObjects != null)
|
||||
//{
|
||||
// Array.Fill(_testObjects, 0);
|
||||
//}
|
||||
_testArray = null;
|
||||
_testRecyclableLongList?.Dispose();
|
||||
_testRecyclableLongList = null;
|
||||
_testPooledList?.Dispose();
|
||||
_testPooledList = null;
|
||||
|
||||
_testObjects = default;
|
||||
_testObjectsAsList = default;
|
||||
_testObjectsAsPooledList?.Dispose();
|
||||
_testObjectsAsPooledList = default;
|
||||
_testObjectsAsRecyclableList?.Dispose();
|
||||
_testObjectsAsRecyclableList = default;
|
||||
_testObjectsAsRecyclableLongList?.Dispose();
|
||||
_testObjectsAsRecyclableLongList = default;
|
||||
base.Cleanup();
|
||||
}
|
||||
}
|
||||
@@ -112,12 +56,12 @@ namespace Recyclable.Collections.Benchmarks
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// using var list = new RecyclableList<object>(initialCapacity: dataCount);
|
||||
// for (long i = 0; i < dataCount; i++)
|
||||
// for (int i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (long i = 0; i < list.LongCount; i++)
|
||||
// for (int i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
@@ -129,14 +73,14 @@ namespace Recyclable.Collections.Benchmarks
|
||||
// public void RecyclableLongList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// long dataCount = TestObjectCount;
|
||||
// int dataCount = TestObjectCount;
|
||||
// using var list = new RecyclableLongList<object>(BlockSize, totalItemsCount: dataCount);
|
||||
// for (long i = 0; i < dataCount; i++)
|
||||
// for (int i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (long i = 0; i < list.LongCount; i++)
|
||||
// for (int i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
@@ -225,7 +169,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new PriorityQueue<object, long>(initialCapacity: dataCount);
|
||||
// var list = new PriorityQueue<object, int>(initialCapacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i], i);
|
||||
@@ -244,7 +188,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableSortedList<long, object>(BlockSize);
|
||||
// var list = new RecyclableSortedList<int, object>(BlockSize);
|
||||
// list.BeginUpdate();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
@@ -266,7 +210,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableSortedList<long, object>(BlockSize);
|
||||
// var list = new RecyclableSortedList<int, object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
@@ -285,7 +229,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new SortedList<long, object>();
|
||||
// var list = new SortedList<int, object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
@@ -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
|
||||
|
||||
+17
-12
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Recyclable.Collections.Benchmarks.POC;
|
||||
|
||||
#pragma warning disable RCS1036, RCS1213, IDE0051
|
||||
|
||||
@@ -31,7 +30,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
|
||||
foreach (var _ in Enumerable.Range(1, 1000))
|
||||
{
|
||||
// benchmark.RecyclableList_Create_WithCapacity();
|
||||
//benchmark.RecyclableList_Create_WithCapacity();
|
||||
}
|
||||
|
||||
benchmark.Cleanup();
|
||||
@@ -39,26 +38,26 @@ namespace Recyclable.Collections.Benchmarks
|
||||
|
||||
static void RunPocBenchmarks()
|
||||
{
|
||||
_ = BenchmarkRunner.Run<BoolOrComparePocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<DelegateVsComparerPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<ModuloPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RefVsInstanceMemberPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<SpanVsArrayBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<LessOperatorVsAndOperatorBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<EqualVsContainsInConsecutiveOrderBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundUpToPowerOf2vsOtherBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<GreaterOperatorVsDoesntEqualOperatorBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<SpanConstructorVsTypecastingPocBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<BoolOrCompareBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<DelegateVsComparerBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<ModuloBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<RefVsInstanceMemberBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<SpanVsArrayBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<LessOperatorVsAndOperatorBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<EqualVsContainsInConsecutiveOrderBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<RoundUpToPowerOf2vsOtherBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<GreaterOperatorVsNotEqualOperatorBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<SpanConstructorVsTypecastingBenchmarks>(BenchmarkConfig);
|
||||
|
||||
//ArraySizeLimitBenchmarks.Run();
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
RunRecyclableCollectionsBenchmarks();
|
||||
// RunPocBenchmarks();
|
||||
// RunRecyclableCollectionsBenchmarks();
|
||||
RunPocBenchmarks();
|
||||
// RunSelectedBenchmarks();
|
||||
// RunAssemblyBenchmarks();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
|
||||
<PackageReference Include="Collections.Benchmarks.Core" Version="0.0.3" />
|
||||
<PackageReference Include="Collections.Pooled" Version="1.0.82" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Recyclable.Collections</PackageId>
|
||||
<PackageVersion>0.0.6</PackageVersion>
|
||||
<PackageVersion>0.0.6.1</PackageVersion>
|
||||
<Authors>Marek Lemańczyk</Authors>
|
||||
<Company>N/A</Company>
|
||||
<Product>Recyclable.Collections</Product>
|
||||
@@ -17,11 +17,14 @@
|
||||
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageReleaseNotes>List<T> compatibility pack added for RecyclableList<T>. Various performance improvements and fixes.</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>List<T> compatibility code moved to Recyclable.Collections.Compatibility.List package. Cleanup.</PackageReleaseNotes>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\logo.png" Pack="true" PackagePath="" Link="logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\LICENSE.md" Pack="true" PackagePath="" Link="LICENSE.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
@@ -31,7 +34,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.5" />
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.12" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,272 +0,0 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityListFind
|
||||
{
|
||||
public static bool Exists<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static T? Find<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return sourceSpan[itemIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public static RecyclableList<T> FindAll<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<T> result = new(sourceItemsCount >> 3);
|
||||
Span<T> resultSpan = result._memoryBlock;
|
||||
int capacity = result._capacity,
|
||||
resultItemsCount = 0;
|
||||
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
if (resultItemsCount + 1 > capacity)
|
||||
{
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1));
|
||||
_ = RecyclableListHelpers<T>.EnsureCapacity(result, resultItemsCount, capacity);
|
||||
resultSpan = result._memoryBlock;
|
||||
}
|
||||
|
||||
resultSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
||||
}
|
||||
}
|
||||
|
||||
result._capacity = capacity;
|
||||
result._count = resultItemsCount;
|
||||
return result;
|
||||
}
|
||||
public static RecyclableList<int> FindAllIndexes<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<int> result = new(sourceItemsCount >> 3);
|
||||
Span<int> resultSpan = result._memoryBlock;
|
||||
int capacity = result._capacity,
|
||||
resultItemsCount = 0;
|
||||
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
if (resultItemsCount + 1 > capacity)
|
||||
{
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1));
|
||||
_ = RecyclableListHelpers<int>.EnsureCapacity(result, resultItemsCount, capacity);
|
||||
resultSpan = result._memoryBlock;
|
||||
}
|
||||
|
||||
resultSpan[resultItemsCount++] = itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
result._capacity = capacity;
|
||||
result._count = resultItemsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int FindIndex<T>(this RecyclableList<T> list, int startIndex, int count, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0 || startIndex >= sourceItemsCount)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindIndex<T>(this RecyclableList<T> list, int startIndex, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0 || startIndex >= sourceItemsCount)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindIndex<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static T? FindLast<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
if (list._count == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return sourceSpan[itemIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public static int FindLastIndex<T>(this RecyclableList<T> list, int startIndex, int count, Predicate<T> match)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
if (startIndex != -1)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||
}
|
||||
}
|
||||
else if (count < 0 || startIndex - count + 1 < 0)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Count();
|
||||
}
|
||||
|
||||
if (startIndex < 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int sourceItemsCount = count; // startIndex - count + 1 >= 0 ? count : startIndex + 1;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int lastItemIndex = startIndex - sourceItemsCount;
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex > lastItemIndex; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindLastIndex<T>(this RecyclableList<T> list, int startIndex, Predicate<T> match)
|
||||
{
|
||||
if (list._count == 0 || startIndex < 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindLastIndex<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
if (list._count == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityListIndexOf
|
||||
{
|
||||
public static int IndexOf<T>(this RecyclableList<T> list, T item, int index) => list._count != 0
|
||||
? Array.IndexOf(list._memoryBlock, item, index, list._count - index)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int IndexOf<T>(this RecyclableList<T> list, T item, int index, int count) => list._count != 0
|
||||
? Array.IndexOf(list._memoryBlock, item, index, count)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int LastIndexOf<T>(this RecyclableList<T> list, T item) => list._count != 0
|
||||
? Array.LastIndexOf(list._memoryBlock, item, list._count - 1)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int LastIndexOf<T>(this RecyclableList<T> list, T item, int index) => list._count != 0
|
||||
? Array.LastIndexOf(list._memoryBlock, item, index)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int LastIndexOf<T>(this RecyclableList<T> list, T item, int index, int count) => list._count != 0
|
||||
? Array.LastIndexOf(list._memoryBlock, item, index, count)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityListInsertRange
|
||||
{
|
||||
private static void InsertRangeEnumerated<T>(this RecyclableList<T> list, int index, IEnumerable<T> items, int growByCount)
|
||||
{
|
||||
var enumerator = items.GetEnumerator();
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int capacity = list._capacity,
|
||||
added = 0,
|
||||
available = capacity - list._count,
|
||||
i,
|
||||
movingBlockLength = list._count - index;
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
if (available > 0)
|
||||
{
|
||||
Array.Copy(memoryBlock, index, memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
|
||||
Span<T> memorySpan = memoryBlock;
|
||||
do
|
||||
{
|
||||
if (index + available + movingBlockLength > capacity)
|
||||
{
|
||||
var capacityBeforeIncrease = capacity;
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)(capacity + growByCount)));
|
||||
_ = RecyclableListHelpers<T>.EnsureCapacity(list, memoryBlock.Length, capacity);
|
||||
memorySpan = memoryBlock = list._memoryBlock;
|
||||
available = capacity - index - movingBlockLength;
|
||||
Array.Copy(memoryBlock, capacityBeforeIncrease - movingBlockLength, memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
|
||||
for (i = 0; i < available; i++)
|
||||
{
|
||||
memorySpan[index++] = enumerator.Current;
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
added++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
added += i;
|
||||
}
|
||||
while (i == available);
|
||||
|
||||
if (i != available)
|
||||
{
|
||||
Array.Copy(memoryBlock, capacity - movingBlockLength, memoryBlock, index, movingBlockLength);
|
||||
if (RecyclableList<T>._needsClearing)
|
||||
{
|
||||
Array.Clear(memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
}
|
||||
|
||||
list._count += added;
|
||||
list._capacity = capacity;
|
||||
}
|
||||
|
||||
private static void InsertRangeWithKnownCount<T>(this RecyclableList<T> list, int index, IEnumerable<T> items, int currentItemsCount, int requiredAdditionalCapacity)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity))));
|
||||
|
||||
Array.Copy(list._memoryBlock, index, list._memoryBlock, index + requiredAdditionalCapacity, list._count - index);
|
||||
Span<T> memorySpan = list._memoryBlock;
|
||||
foreach (var item in items)
|
||||
{
|
||||
memorySpan[index++] = item;
|
||||
}
|
||||
|
||||
list._count += requiredAdditionalCapacity;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, in Array items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
Array.Copy(items, items.GetLowerBound(0), memoryBlock, index, items.Length);
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, in T[] items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
new ReadOnlySpan<T>(items).CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, ReadOnlySpan<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
items.CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, Span<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
items.CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, List<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, ICollection items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(list._memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, ICollection<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, RecyclableList<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items._count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items._count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
new ReadOnlySpan<T>(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count));
|
||||
list._count += items._count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, RecyclableLongList<T> items)
|
||||
{
|
||||
if (items._longCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int oldCount = list._count;
|
||||
long sourceItemsCount = items._longCount;
|
||||
if (oldCount + sourceItemsCount > int.MaxValue)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), $"The total number of items in source and target table exceeds the maximum capacity of {nameof(RecyclableList<T>)}, equal {int.MaxValue}. Please consider using {nameof(RecyclableLongList<T>)}, instead");
|
||||
}
|
||||
|
||||
int targetCapacity = oldCount + (int)sourceItemsCount;
|
||||
if (list._capacity < targetCapacity)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, oldCount - index);
|
||||
Span<T> targetSpan = new(list._memoryBlock, index, list._capacity - index),
|
||||
itemsSpan;
|
||||
|
||||
int blockIndex,
|
||||
sourceBlockSize = items._blockSize,
|
||||
lastBlockIndex = (int)(sourceItemsCount >> items._blockSizePow2BitShift) - 1;
|
||||
|
||||
for (blockIndex = 0; blockIndex <= lastBlockIndex; blockIndex++)
|
||||
{
|
||||
itemsSpan = new(items._memoryBlocks[blockIndex], 0, sourceBlockSize);
|
||||
itemsSpan.CopyTo(targetSpan);
|
||||
targetSpan = targetSpan[sourceBlockSize..];
|
||||
}
|
||||
|
||||
if (blockIndex == 0)
|
||||
{
|
||||
itemsSpan = new(items._memoryBlocks[blockIndex], 0, (int)sourceItemsCount);
|
||||
itemsSpan.CopyTo(targetSpan);
|
||||
}
|
||||
else if (blockIndex <= items._lastBlockWithData)
|
||||
{
|
||||
itemsSpan = new(items._memoryBlocks[blockIndex], 0, items._nextItemIndex > 0 ? items._nextItemIndex : sourceBlockSize);
|
||||
itemsSpan.CopyTo(targetSpan);
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static IEnumerator InsertRange<T>(this RecyclableList<T> list, int index, IEnumerable source, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
int targetItemIndex = list._count;
|
||||
Span<T> memorySpan;
|
||||
|
||||
int i;
|
||||
var enumerator = source.GetEnumerator();
|
||||
|
||||
int capacity = list._capacity;
|
||||
memorySpan = list._memoryBlock;
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
int available = capacity - targetItemIndex;
|
||||
do
|
||||
{
|
||||
if (targetItemIndex + growByCount > capacity)
|
||||
{
|
||||
capacity = RecyclableListHelpers<T>.EnsureCapacity(list, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount))));
|
||||
memorySpan = list._memoryBlock;
|
||||
available = capacity - targetItemIndex;
|
||||
}
|
||||
|
||||
for (i = 0; i < available; i++)
|
||||
{
|
||||
memorySpan[targetItemIndex++] = (T)enumerator.Current;
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i >= available);
|
||||
}
|
||||
|
||||
list._capacity = capacity;
|
||||
list._count = targetItemIndex;
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, IReadOnlyList<T> items)
|
||||
{
|
||||
int sourceItemsCount = items.Count;
|
||||
if (list._capacity < list._count + sourceItemsCount)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + sourceItemsCount))));
|
||||
}
|
||||
|
||||
Span<T> memorySpan = new(list._memoryBlock, list._count, sourceItemsCount);
|
||||
for (var sourceItemIndex = 0; sourceItemIndex < sourceItemsCount; sourceItemIndex++)
|
||||
{
|
||||
memorySpan[sourceItemIndex] = items[sourceItemIndex];
|
||||
}
|
||||
|
||||
list._count += sourceItemsCount;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, IEnumerable<T> items, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
if (items is RecyclableList<T> sourceRecyclableList)
|
||||
{
|
||||
InsertRange(list, index, sourceRecyclableList);
|
||||
}
|
||||
else if (items is RecyclableLongList<T> sourceRecyclableLongList)
|
||||
{
|
||||
InsertRange(list, index, sourceRecyclableLongList);
|
||||
}
|
||||
else if (items is T[] sourceArray)
|
||||
{
|
||||
InsertRange(list, index, sourceArray);
|
||||
}
|
||||
else if (items is Array sourceArrayWithObjects)
|
||||
{
|
||||
InsertRange(list, index, sourceArrayWithObjects);
|
||||
}
|
||||
else if (items is List<T> sourceList)
|
||||
{
|
||||
InsertRange(list, index, sourceList);
|
||||
}
|
||||
else if (items is ICollection<T> sourceICollection)
|
||||
{
|
||||
InsertRange(list, index, sourceICollection);
|
||||
}
|
||||
else if (items is ICollection sourceICollectionWithObjects)
|
||||
{
|
||||
InsertRange(list, index, sourceICollectionWithObjects);
|
||||
}
|
||||
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
||||
{
|
||||
InsertRange(list, index, sourceIReadOnlyList);
|
||||
}
|
||||
else if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity) && requiredAdditionalCapacity != 0)
|
||||
{
|
||||
InsertRangeWithKnownCount(list, index, items, list._count, requiredAdditionalCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertRangeEnumerated(list, index, items, growByCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Numerics;
|
||||
using Recyclable.Collections.Pools;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityList
|
||||
{
|
||||
public static ReadOnlyCollection<T> AsReadOnly<T>(this RecyclableList<T> list) => new(list);
|
||||
|
||||
public static int BinarySearch<T>(this RecyclableList<T> list, T item)
|
||||
=> Array.BinarySearch(list._memoryBlock, 0, list._count, item);
|
||||
|
||||
public static int BinarySearch<T>(this RecyclableList<T> list, T item, IComparer<T>? comparer)
|
||||
=> Array.BinarySearch(list._memoryBlock, 0, list._count, item, comparer);
|
||||
|
||||
public static int BinarySearch<T>(this RecyclableList<T> list, int index, int count, T item, IComparer<T>? comparer)
|
||||
=> Array.BinarySearch(list._memoryBlock, index, count, item, comparer);
|
||||
|
||||
public static RecyclableList<TOutput> ConvertAll<T, TOutput>(this RecyclableList<T> list, Converter<T, TOutput> converter)
|
||||
{
|
||||
int itemsCount = list._count;
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
RecyclableList<TOutput> result = new(itemsCount);
|
||||
TOutput[] resultSpan = result._memoryBlock;
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (int bufferIndex = 0; bufferIndex < itemsCount; bufferIndex++)
|
||||
{
|
||||
resultSpan[bufferIndex] = converter(sourceSpan[bufferIndex]);
|
||||
}
|
||||
|
||||
result._count = itemsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void CopyTo<T>(this RecyclableList<T> list, T[] array) => Array.Copy(list._memoryBlock, array, list._count);
|
||||
|
||||
public static void CopyTo<T>(this RecyclableList<T> list, int index, T[] array, int arrayIndex, int count) => Array.Copy(list._memoryBlock, index, array, arrayIndex, count);
|
||||
|
||||
public static void ForEach<T>(this RecyclableList<T> list, Action<T> action)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
action(sourceSpan[itemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
public static RecyclableList<T> GetRange<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
int sourceItemsCount = index + count <= list._count ? count : list._count - index;
|
||||
if (sourceItemsCount <= 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<T> result = new(sourceItemsCount);
|
||||
Span<T> targetSpan = result._memoryBlock;
|
||||
int resultItemsCount = 0;
|
||||
sourceItemsCount += index;
|
||||
for (var itemIndex = index; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
targetSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
||||
}
|
||||
|
||||
result._count = resultItemsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int RemoveAll<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
using var allIndexes = list.FindAllIndexes(match);
|
||||
int foundItemsCount = allIndexes._count;
|
||||
if (foundItemsCount == 0)
|
||||
{
|
||||
return foundItemsCount;
|
||||
}
|
||||
|
||||
for (int removed = 0; removed < foundItemsCount; removed++)
|
||||
{
|
||||
var indexToRemove = allIndexes[removed] - removed;
|
||||
Array.Copy(list._memoryBlock, indexToRemove + 1, list._memoryBlock, indexToRemove, list._count - indexToRemove - removed - 1);
|
||||
}
|
||||
|
||||
if (RecyclableList<T>._needsClearing)
|
||||
{
|
||||
Array.Clear(list._memoryBlock, list._count - foundItemsCount, foundItemsCount);
|
||||
}
|
||||
|
||||
list._count -= foundItemsCount;
|
||||
list._version++;
|
||||
return foundItemsCount;
|
||||
}
|
||||
|
||||
public static void RemoveRange<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
int oldCount = list._count;
|
||||
count = count - index + 1 <= oldCount ? count : oldCount - index + 1;
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (index + count < oldCount)
|
||||
{
|
||||
Array.Copy(list._memoryBlock, index + count, list._memoryBlock, index, oldCount - count - index);
|
||||
}
|
||||
|
||||
if (RecyclableList<T>._needsClearing)
|
||||
{
|
||||
Array.Clear(list._memoryBlock, oldCount - count, count);
|
||||
}
|
||||
|
||||
list._count -= count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Reverse<T>(this RecyclableList<T> list)
|
||||
{
|
||||
Array.Reverse(list._memoryBlock, 0, list._count);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Reverse<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
Array.Reverse(list._memoryBlock, index, count);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, Comparison<T> comparison)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count, new ComparisonToComparerAdapter<T>(comparison));
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, IComparer<T>? comparer)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count, comparer);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, int index, int count, IComparer<T>? comparer)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, index, count, comparer);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static T[] ToArray<T>(this RecyclableList<T> list)
|
||||
{
|
||||
T[] result = new T[list._count];
|
||||
new ReadOnlySpan<T>(list._memoryBlock, 0, list._count).CopyTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void TrimExcess<T>(this RecyclableList<T> list)
|
||||
{
|
||||
var requiredCapacity = list._count >= RecyclableDefaults.InitialCapacity ? list._count : RecyclableDefaults.InitialCapacity;
|
||||
|
||||
T[] oldMemoryBlock = list._memoryBlock;
|
||||
T[] result = requiredCapacity >= RecyclableDefaults.MinPooledArrayLength && BitOperations.IsPow2(requiredCapacity)
|
||||
? RecyclableArrayPool<T>.RentShared(requiredCapacity)
|
||||
: new T[requiredCapacity];
|
||||
|
||||
new ReadOnlySpan<T>(oldMemoryBlock, 0, list._count).CopyTo(result);
|
||||
|
||||
if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, RecyclableList<T>._needsClearing);
|
||||
}
|
||||
|
||||
list._memoryBlock = result;
|
||||
list._capacity = requiredCapacity;
|
||||
}
|
||||
|
||||
public static bool TrueForAll<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (!match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public class CustomIList<T> : IList<T>
|
||||
{
|
||||
protected List<T> _list;
|
||||
|
||||
public CustomIList()
|
||||
{
|
||||
_list = new List<T>();
|
||||
}
|
||||
|
||||
public CustomIList(IEnumerable<T> items)
|
||||
{
|
||||
_list = new List<T>(items);
|
||||
}
|
||||
|
||||
public T this[int index] { get => _list[index]; set => _list[index] = value; }
|
||||
public int Count => _list.Count;
|
||||
public bool IsReadOnly => false;
|
||||
public void Add(T item) => _list.Add(item);
|
||||
public void Clear() => _list.Clear();
|
||||
public bool Contains(T item) => _list.Contains(item);
|
||||
public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(0, array, arrayIndex, _list.Count);
|
||||
public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
|
||||
public int IndexOf(T item) => _list.IndexOf(item);
|
||||
public void Insert(int index, T item) => _list.Insert(index, item);
|
||||
public bool Remove(T item) => _list.Remove(item);
|
||||
public void RemoveAt(int index) => _list.RemoveAt(index);
|
||||
IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public class EnumerableWithoutCount<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly IEnumerable<T> _testData;
|
||||
|
||||
public EnumerableWithoutCount(IEnumerable<T> testData)
|
||||
{
|
||||
_testData = testData;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => _testData.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => _testData.GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,19 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Open.Numeric.Primes" Version="3.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.5.0">
|
||||
<PackageReference Include="Recyclable.Collections.TestData" Version="0.0.2" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.5.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,282 +0,0 @@
|
||||
using MoreLinq;
|
||||
using Open.Numeric.Primes;
|
||||
using Recyclable.Collections;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public static class RecyclableLongListTestData
|
||||
{
|
||||
|
||||
private static readonly object[] _sourceRefData = Enumerable.Range(1, 100).Cast<object>().ToArray();
|
||||
public static object[] SourceRefData => _sourceRefData;
|
||||
|
||||
public static IEnumerable<long> CreateTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object> CreateRefTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly IEnumerable<long> ItemsCountVariants = new long[]
|
||||
{
|
||||
//RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, 127, 128, 129, RecyclableDefaults.MinItemsCountForParallelization
|
||||
0, 1, 2, 3, 7, 10, 16, RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, RecyclableDefaults.MinPooledArrayLength * 100
|
||||
};
|
||||
|
||||
public static readonly IEnumerable<object[]> ItemsCountTestCases = ItemsCountVariants.Select(x => new object[] { (int)x });
|
||||
|
||||
public static readonly IEnumerable<int> BlockSizeVariants = new int[]
|
||||
{
|
||||
1, 2, 4, 16, RecyclableDefaults.MinPooledArrayLength - 5, (int)BitOperations.RoundUpToPowerOf2(RecyclableDefaults.MinPooledArrayLength)
|
||||
};
|
||||
|
||||
private static bool IsValidBlockSize(long itemsCount, long blockSize) => itemsCount is < 1024 || blockSize is > 8;
|
||||
|
||||
private static IEnumerable<object[]> GetTargetDataVariants()
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { itemsCount, targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TargetDataVariants => GetTargetDataVariants();
|
||||
|
||||
private static IEnumerable<object[]> CombineSourceDataWithBlockSize(IEnumerable<object[]> sourceData)
|
||||
{
|
||||
foreach (var testData in sourceData)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize((long)testData[2], targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { testData[0], testData[1], testData[2], targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(long itemsCount, bool refType)
|
||||
{
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
switch (refType)
|
||||
{
|
||||
case false:
|
||||
long[] testData = CreateTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"Array[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"ICollection[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"ICollection<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable<T>[{itemsCount}] without non-enumerated count", new EnumerableWithoutCount<long>(testData), itemsCount };
|
||||
yield return new object[] { $"IList<T>[{itemsCount}]", new CustomIList<long>(testData), itemsCount };
|
||||
yield return new object[] { $"IReadOnlyList<T>[{itemsCount}])", testData, itemsCount };
|
||||
yield return new object[] { $"List<T>[{itemsCount}]", testData.ToList(), itemsCount };
|
||||
yield return new object[] { $"ReadOnlySpan<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"RecyclableList<T>[{itemsCount}]", testData.ToRecyclableList(), itemsCount };
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<T>[itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize}]",
|
||||
testData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"Span<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"T[{itemsCount}]", testData, itemsCount };
|
||||
break;
|
||||
|
||||
case true:
|
||||
IEnumerable<object> testRefData = CreateRefTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"Array[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"ICollection(itemsCount: {itemsCount}", testRefData, itemsCount };
|
||||
yield return new object[] { $"ICollection<T>(itemsCount: {itemsCount}", testRefData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable(itemsCount: {itemsCount})", testRefData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable<T>(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount<object>(testRefData), itemsCount };
|
||||
yield return new object[] { $"IList<T>(itemsCount: {itemsCount})", new CustomIList<object>(testRefData), itemsCount };
|
||||
yield return new object[] { $"IReadOnlyList<T>(itemsCount: {itemsCount})", testRefData, itemsCount };
|
||||
yield return new object[] { $"List<T>(itemsCount: {itemsCount}", testRefData.ToList(), itemsCount };
|
||||
yield return new object[] { $"ReadOnlySpan<T>[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"RecyclableList<T>(itemsCount: {itemsCount})", testRefData.ToRecyclableList(), itemsCount };
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<T>(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})",
|
||||
testRefData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"Span<T>[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"T[{itemsCount}]", testRefData, itemsCount };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(bool refType)
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var variant in CreateSourceDataVariants(itemsCount, refType))
|
||||
{
|
||||
yield return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> EmptySourceDataVariants => CreateSourceDataVariants(0, false);
|
||||
public static IEnumerable<object[]> SourceDataVariants => CreateSourceDataVariants(false);
|
||||
public static IEnumerable<object[]> SourceDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var testCase in CreateSourceDataVariants(false).Where(testCase => (long)testCase[2] > 0))
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceRefDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<object[]> testCases = CreateSourceDataVariants(true).Where(testCase => (long)testCase[2] > 0);
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeVariants => CombineSourceDataWithBlockSize(SourceDataVariants);
|
||||
public static IEnumerable<object[]> SourceRefDataVariants => CreateSourceDataVariants(true);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeVariants { get; } = CombineSourceDataWithBlockSize(SourceRefDataVariants);
|
||||
|
||||
private static IEnumerable<long> _initialItemIndexVariants => new long[] { 0, 1, 2, 3, 4, 5 };
|
||||
private static IEnumerable<long> CreateItemIndexVariants(long itemsCount, int blockSize)
|
||||
{
|
||||
IEnumerable<long> primes = _initialItemIndexVariants.Concat(
|
||||
_initialItemIndexVariants.SelectMany(index => new long[] { blockSize - index, blockSize + index })
|
||||
//new long[] { blockSize - 3, blockSize - 2, blockSize - 1, blockSize, blockSize + 1, blockSize + 2, blockSize + 3 }
|
||||
).ToArray();
|
||||
|
||||
IEnumerable<long> second = Prime.Numbers.StartingAt(7)
|
||||
.TakeUntil(prime =>
|
||||
prime > ((blockSize * 2) - 1) ||
|
||||
prime >= itemsCount
|
||||
);
|
||||
|
||||
primes = primes.Concat(second).ToArray();
|
||||
|
||||
primes = primes.Concat(
|
||||
primes.Select(index => itemsCount - index - 1)
|
||||
)
|
||||
.Where(index => itemsCount > 0 && index >= 0 && index < itemsCount).ToArray()
|
||||
.Distinct().ToArray();
|
||||
|
||||
return primes;
|
||||
|
||||
//IEnumerable<long> CreateItemIndexVariants()
|
||||
//{
|
||||
//if (itemsCount > 0)
|
||||
//{
|
||||
// yield return 0;
|
||||
//}
|
||||
|
||||
//foreach (long prime in primes)
|
||||
//{
|
||||
// yield return prime;
|
||||
|
||||
// long index = itemsCount - prime;
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//for (long index = itemsCount - (blockSize * 2) - 1; index < itemsCount; index++)
|
||||
//{
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if ((blockSize / 16 * 16) + 1 < itemsCount)
|
||||
//{
|
||||
// yield return (blockSize / 16 * 16) + 1;
|
||||
//}
|
||||
//}
|
||||
|
||||
//return CreateItemIndexVariants();
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CombineSourceRefDataWithBlockSizeWithItemIndex(bool refType)
|
||||
{
|
||||
IEnumerable<object[]> sourceData = refType switch
|
||||
{
|
||||
false => SourceDataWithBlockSizeVariants,
|
||||
true => SourceRefDataWithBlockSizeVariants
|
||||
};
|
||||
|
||||
foreach (var testCase in sourceData)
|
||||
{
|
||||
long itemsCount = (long)testCase[2];
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
long[] itemIndexes = CreateItemIndexVariants(itemsCount, (int)testCase[3])
|
||||
.Where(_ => IsValidBlockSize((long)testCase[2], (int)testCase[3]))
|
||||
.ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], (long)testCase[2], (int)testCase[3], itemIndexes };
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(false);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(true);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using FluentAssertions;
|
||||
using Recyclable.Collections;
|
||||
using Recyclable.Collections.TestData;
|
||||
using Recyclable.Collections.Linq;
|
||||
using System.Collections;
|
||||
using System.Numerics;
|
||||
|
||||
Reference in new issue
Block a user