Merge branch 'recyclable-block-list-added'
This commit is contained in:
commit
1c8d1998f5
82 files changed
+17135
-1057
No files matched your search
@@ -0,0 +1,51 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_Add()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
var list = new List<long>();
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Add()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new PooledList<long>(ClearMode.Auto);
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Add()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new RecyclableList<long>();
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Add()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new RecyclableLongList<long>();
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_AddRangeWhenSourceIsArray()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = new List<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void PooledList_AddRangeWhenSourceIsArray()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new PooledList<long>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableList_AddRangeWhenSourceIsArray()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableList<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRangeWhenSourceIsArray()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_AddRangeWhenSourceIsIEnumerable()
|
||||
{
|
||||
var data = TestObjectsAsIEnumerable;
|
||||
var list = new List<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void PooledList_AddRangeWhenSourceIsIEnumerable()
|
||||
{
|
||||
var data = TestObjectsAsIEnumerable;
|
||||
using var list = new PooledList<long>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableList_AddRangeWhenSourceIsIEnumerable()
|
||||
{
|
||||
var data = TestObjectsAsIEnumerable;
|
||||
using var list = new RecyclableList<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRangeWhenSourceIsIEnumerable()
|
||||
{
|
||||
var data = TestObjectsAsIEnumerable;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_AddRangeWhenSourceIsIList()
|
||||
{
|
||||
var data = (IList<long>)TestObjectsAsRecyclableLongList;
|
||||
var list = new List<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void PooledList_AddRangeWhenSourceIsIList()
|
||||
{
|
||||
var data = (IList<long>)TestObjectsAsPooledList;
|
||||
using var list = new PooledList<long>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableList_AddRangeWhenSourceIsIList()
|
||||
{
|
||||
var data = (IList<long>)TestObjectsAsRecyclableLongList;
|
||||
using var list = new RecyclableList<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRangeWhenSourceIsIList()
|
||||
{
|
||||
var data = (IList<long>)TestObjectsAsRecyclableLongList;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_AddRangeWhenSourceIsList()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
var list = new List<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void PooledList_AddRangeWhenSourceIsList()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
using var list = new PooledList<long>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableList_AddRangeWhenSourceIsList()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
using var list = new RecyclableList<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRangeWhenSourceIsList()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void PooledList_AddRangeWhenSourceIsPooledList()
|
||||
{
|
||||
var data = TestObjectsAsPooledList;
|
||||
using var list = new PooledList<long>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableList_AddRangeWhenSourceIsRecyclableList()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
using var list = new RecyclableList<long>();
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRangeWhenSourceIsRecyclableList()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_AddRange_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
var list = new List<long>(dataCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void PooledList_AddRange_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new PooledList<long>(capacity: dataCount, ClearMode.Auto);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableList_AddRange_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new RecyclableList<long>(dataCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRange_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: dataCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_Add_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
var list = new List<long>(dataCount);
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Add_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new PooledList<long>(capacity: dataCount, ClearMode.Auto);
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Add_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new RecyclableList<long>(dataCount);
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Add_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: dataCount);
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Contains_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[i]) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void List_Contains_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Contains_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Contains_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Contains_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Contains_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_Contains_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Contains_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Contains_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Contains_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Contains(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Count()
|
||||
{
|
||||
var data = TestObjects;
|
||||
DoNothing(data.Length);
|
||||
}
|
||||
|
||||
public void List_Count()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
DoNothing(data.Count);
|
||||
}
|
||||
|
||||
public void PooledList_Count()
|
||||
{
|
||||
var data = TestObjectsAsPooledList;
|
||||
DoNothing(data.Count);
|
||||
}
|
||||
|
||||
public void RecyclableList_Count()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
DoNothing(data.Count);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Count()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
DoNothing(data.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public static void List_Create()
|
||||
{
|
||||
var list = new List<long>();
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public static void PooledList_Create()
|
||||
{
|
||||
using var list = new PooledList<long>(ClearMode.Auto);
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public static void RecyclableList_Create()
|
||||
{
|
||||
using var list = new RecyclableList<long>();
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public static void RecyclableLongList_Create()
|
||||
{
|
||||
using var list = new RecyclableLongList<long>();
|
||||
DoNothing(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Create_WithCapacity()
|
||||
{
|
||||
var data = new long[TestObjectCount];
|
||||
DoNothing(data);
|
||||
}
|
||||
|
||||
public void List_Create_WithCapacity()
|
||||
{
|
||||
var list = new List<long>(TestObjectCount);
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void PooledList_Create_WithCapacity()
|
||||
{
|
||||
using var list = new PooledList<long>(capacity: TestObjectCount, ClearMode.Auto);
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void RecyclableList_Create_WithCapacity()
|
||||
{
|
||||
using var list = new RecyclableList<long>(TestObjectCount);
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Create_WithCapacity()
|
||||
{
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
DoNothing(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_GetItem()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void List_GetItem()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_GetItem()
|
||||
{
|
||||
var data = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_GetItem()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_GetItem()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_GetItem_AsSpan()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
int blockSize = data.BlockSize;
|
||||
int nextItemBlockIndex = data.NextItemBlockIndex;
|
||||
|
||||
var memoryBlocks = new Span<long[]>(data.AsArray, 0, data.LastBlockWithData + 1);
|
||||
for (var blockIndex = 0; blockIndex < nextItemBlockIndex; blockIndex++)
|
||||
{
|
||||
var memoryBlock = new Span<long>(memoryBlocks[blockIndex], 0, blockSize);
|
||||
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextItemBlockIndex == data.LastBlockWithData)
|
||||
{
|
||||
var memoryBlock = new Span<long>(memoryBlocks[nextItemBlockIndex], 0, data.NextItemIndex);
|
||||
for (var itemIndex = 0; itemIndex < memoryBlock.Length; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_GetItem_AsArray()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
int blockSize = data.BlockSize;
|
||||
int nextItemBlockIndex = data.NextItemBlockIndex;
|
||||
|
||||
var memoryBlocks = data.AsArray;
|
||||
for (var blockIndex = 0; blockIndex < nextItemBlockIndex; blockIndex++)
|
||||
{
|
||||
var memoryBlock = memoryBlocks[blockIndex];
|
||||
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
if (nextItemBlockIndex == data.LastBlockWithData)
|
||||
{
|
||||
var memoryBlock = memoryBlocks[nextItemBlockIndex];
|
||||
blockSize = data.NextItemIndex;
|
||||
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_GetItem_AsForEach()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
foreach (var item in data)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_GetItem_AsWhile()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
long dataCount = TestObjectCount;
|
||||
if (dataCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int blockSize = data.BlockSize;
|
||||
int nextItemBlockIndex = data.NextItemBlockIndex;
|
||||
int itemIndex = 0;
|
||||
int blockIndex = 0;
|
||||
var memoryBlocks = data.AsArray;
|
||||
var memoryBlock = memoryBlocks[0];
|
||||
while (blockIndex < nextItemBlockIndex)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex]);
|
||||
if (itemIndex + 1 < blockSize)
|
||||
{
|
||||
itemIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
blockIndex++;
|
||||
memoryBlock = memoryBlocks[blockIndex];
|
||||
itemIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextItemBlockIndex == data.LastBlockWithData)
|
||||
{
|
||||
memoryBlock = memoryBlocks[nextItemBlockIndex];
|
||||
blockSize = data.NextItemIndex;
|
||||
while (itemIndex < blockSize)
|
||||
{
|
||||
DoNothing(memoryBlock[itemIndex++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_IndexOf_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[i]));
|
||||
DoNothing(Array.IndexOf(list, data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_IndexOf_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_IndexOf_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_IndexOf_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_IndexOf_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_LongIndexOf_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
DoNothing(list.LongIndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_IndexOf_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_IndexOf_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_IndexOf_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_IndexOf_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_IndexOf_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_LongIndexOf_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.LongIndexOf(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_IndexOf_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.IndexOf(list, data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_IndexOf_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_IndexOf_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_IndexOf_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_IndexOf_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.IndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_LongIndexOf_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.LongIndexOf(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_LongCount()
|
||||
{
|
||||
var data = TestObjects;
|
||||
DoNothing(data.LongLength);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_LongCount()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
DoNothing(data.LongCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,35 +17,35 @@ namespace Recyclable.Collections.Benchmarks
|
||||
public RecyclableCollectionsBenchmarks() : base()
|
||||
{
|
||||
TestObjectCount = 1;
|
||||
// BaselineBenchmarkType = RecyclableCollectionsBenchmarkSource.PooledList;
|
||||
BaselineBenchmarkType = RecyclableCollectionsBenchmarkSource.List;
|
||||
BenchmarkType = RecyclableCollectionsBenchmarkSource.RecyclableLongList;
|
||||
}
|
||||
|
||||
[Params
|
||||
(
|
||||
//RecyclableCollectionsBenchmarkType.Add_WithCapacity,
|
||||
//RecyclableCollectionsBenchmarkType.Add,
|
||||
//RecyclableCollectionsBenchmarkType.AddRange_WithCapacity,
|
||||
//RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsArray,
|
||||
//RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable,
|
||||
//RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList,
|
||||
//RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsList,
|
||||
//RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType,
|
||||
//RecyclableCollectionsBenchmarkType.Contains_FirstItems,
|
||||
//RecyclableCollectionsBenchmarkType.Contains_LastItems,
|
||||
//RecyclableCollectionsBenchmarkType.Count,
|
||||
//RecyclableCollectionsBenchmarkType.Create_WithCapacity,
|
||||
//RecyclableCollectionsBenchmarkType.Create,
|
||||
//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.Add_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.Add,
|
||||
RecyclableCollectionsBenchmarkType.AddRange_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsArray,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsList,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType,
|
||||
RecyclableCollectionsBenchmarkType.Contains_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.Contains_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.Count,
|
||||
RecyclableCollectionsBenchmarkType.Create_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.Create,
|
||||
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
|
||||
)]
|
||||
|
||||
public RecyclableCollectionsBenchmarkType TestCase { get; set; } = RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases;
|
||||
@@ -58,10 +58,10 @@ namespace Recyclable.Collections.Benchmarks
|
||||
|
||||
[Params
|
||||
(
|
||||
//RecyclableCollectionsBenchmarkSource.Array,
|
||||
//RecyclableCollectionsBenchmarkSource.List,
|
||||
//RecyclableCollectionsBenchmarkSource.PooledList
|
||||
//RecyclableCollectionsBenchmarkSource.RecyclableList,
|
||||
RecyclableCollectionsBenchmarkSource.Array,
|
||||
RecyclableCollectionsBenchmarkSource.List,
|
||||
RecyclableCollectionsBenchmarkSource.PooledList,
|
||||
RecyclableCollectionsBenchmarkSource.RecyclableList,
|
||||
RecyclableCollectionsBenchmarkSource.RecyclableLongList
|
||||
)]
|
||||
public override RecyclableCollectionsBenchmarkSource BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = value; }
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_RemoveAt_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = new List<long>(data);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_RemoveAt_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new PooledList<long>(data, ClearMode.Auto);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_RemoveAt_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableList<long>(data);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_RemoveAt_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableLongList<long>(data, minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_RemoveAt_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = new List<long>(data);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_RemoveAt_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new PooledList<long>(data, ClearMode.Auto);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_RemoveAt_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableList<long>(data);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_RemoveAt_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableLongList<long>(data, minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_Remove_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = new List<long>(data);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Remove_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new PooledList<long>(data, ClearMode.Auto);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Remove_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableList<long>(data);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Remove_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableLongList<long>(data, minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void List_Remove_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = new List<long>(data);
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Remove_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new PooledList<long>(data, ClearMode.Auto);
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Remove_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableList<long>(data);
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Remove_LastItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableLongList<long>(data, minBlockSize: BlockSize, expectedItemsCount: TestObjectCount);
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_SetItem()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
long index = 0;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[index] = TestObjects[index++];
|
||||
}
|
||||
}
|
||||
|
||||
public void List_SetItem()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = TestObjects[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_SetItem()
|
||||
{
|
||||
var data = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = TestObjects[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_SetItem()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = TestObjects[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_SetItem()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableLongList;
|
||||
var dataCount = TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = TestObjects[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using MiscUtil;
|
||||
using MiscUtil.Extensions;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public delegate T Compare<T>(T x, T y);
|
||||
|
||||
public readonly struct MyComparerReadOnlyStruct<T> : IComparer<T>
|
||||
{
|
||||
public int Compare(T? x, T? y) => Operator.Subtract(x, y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public struct MyComparerStruct<T> : IComparer<T>
|
||||
{
|
||||
public int Compare(T? x, T? y) => Operator.Subtract(x, y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public class MyComparer : IComparer<long>
|
||||
{
|
||||
public int Compare(long x, long y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class DelegateVsComparerBenchmark
|
||||
{
|
||||
private static readonly Comparer<long> _comparer = Comparer<long>.Default;
|
||||
|
||||
private const int _objectCount = 1_000_000;
|
||||
private static readonly IEnumerable<long> _testObjects = Enumerable.Range(1, _objectCount).Select(x => (long)x);
|
||||
private static readonly IEnumerable<Func<long, long, int>> _testListOfFunctions = _testObjects.Select<long, Func<long, long, int>>(static x => new MyComparer().Compare);
|
||||
private static readonly IEnumerable<IComparer<long>> _testListOfComparers = _testObjects.Select(x => (IComparer<long>)new MyComparer());
|
||||
private static readonly IEnumerable<Compare<long>> _testListOfDelegates = _testObjects.Select(x => new Compare<long>((x, y) => new MyComparer().Compare(x, y)));
|
||||
private static readonly IEnumerable<Func<long, long, int>> _testListOfLocalFunctions = GetLocalFunctions(_testObjects);
|
||||
private static readonly IEnumerable<MyComparer> _testListOfClasses = _testObjects.Select(x => new MyComparer());
|
||||
private static readonly IEnumerable<MyComparerStruct<long>> _testListOfStructs = _testObjects.Select(x => new MyComparerStruct<long>());
|
||||
private static readonly IEnumerable<IComparer<long>> _testListOfBoxedStructs = _testObjects.Select(x => (IComparer<long>)new MyComparerStruct<long>());
|
||||
private static IEnumerable<TComparer> _testListOfUnboxedStructs<TComparer, TValue>() where TComparer : IComparer<TValue>, new()
|
||||
{
|
||||
foreach (var item 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 item in testObjects)
|
||||
{
|
||||
yield return compareFunc;
|
||||
}
|
||||
}
|
||||
|
||||
private static 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]);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void Comparer()
|
||||
{
|
||||
TestWithComparer(_comparer);
|
||||
}
|
||||
|
||||
private static 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]);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Func()
|
||||
{
|
||||
TestWithFunc((x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void StaticFunc()
|
||||
{
|
||||
TestWithFunc(static (x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
private static void TestWithDelegate<T>(Compare<long> compareFunc)
|
||||
{
|
||||
var testData = _testObjects.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Delegate()
|
||||
{
|
||||
TestWithDelegate<long>((x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class ListVsLinkedListBenchmark
|
||||
{
|
||||
private const int _objectCount = 1_000_000;
|
||||
private const int _blockSize = 100_000;
|
||||
private static readonly object[] _testObjects = Enumerable.Range(1, _objectCount).Select(x => new object()).ToArray();
|
||||
|
||||
private static void DoNothing<T>(T obj)
|
||||
{
|
||||
_ = obj;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Array()
|
||||
{
|
||||
var list = new object[_testObjects.LongLength];
|
||||
for (var i = 0; i < _testObjects.Length; i++)
|
||||
{
|
||||
list[i] = _testObjects[i];
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.LongLength; i++)
|
||||
{
|
||||
DoNothing(list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void RecyclableList()
|
||||
{
|
||||
using var list = new RecyclableList<object>(_blockSize);
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Add(_testObjects[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
DoNothing(_testObjects[i]);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void List()
|
||||
{
|
||||
var list = new List<object>();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Add(_testObjects[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
DoNothing(list[i]);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void LinkedList()
|
||||
{
|
||||
var list = new LinkedList<object>();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
_ = list.AddLast(_testObjects[i]);
|
||||
}
|
||||
|
||||
foreach (var node in list)
|
||||
{
|
||||
DoNothing(node);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RecyclableQueue()
|
||||
{
|
||||
var list = new RecyclableQueue<object>(_blockSize);
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Enqueue(_testObjects[i]);
|
||||
}
|
||||
|
||||
foreach (var node in list)
|
||||
{
|
||||
DoNothing(node);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void Queue()
|
||||
{
|
||||
var list = new Queue<object>();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Enqueue(_testObjects[i]);
|
||||
}
|
||||
|
||||
foreach (var node in list)
|
||||
{
|
||||
DoNothing(node);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void PriorityQueue()
|
||||
{
|
||||
var list = new PriorityQueue<object, long>();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Enqueue(_testObjects[i], i);
|
||||
}
|
||||
|
||||
while (list.Count > 0)
|
||||
{
|
||||
var node = list.Dequeue();
|
||||
DoNothing(node);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void RecyclableSortedList_InUpdateMode()
|
||||
{
|
||||
var list = new RecyclableSortedList<long, object>(_blockSize);
|
||||
list.BeginUpdate();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Add(i, _testObjects[i]);
|
||||
}
|
||||
|
||||
list.EndUpdate();
|
||||
|
||||
for (var i = 0; i < list.LongCount; i++)
|
||||
{
|
||||
DoNothing(_testObjects[i]);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void RecyclableSortedList()
|
||||
{
|
||||
var list = new RecyclableSortedList<long, object>(_blockSize);
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Add(i, _testObjects[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.LongCount; i++)
|
||||
{
|
||||
DoNothing(_testObjects[i]);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void SortedList()
|
||||
{
|
||||
var list = new SortedList<long, object>();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Add(i, _testObjects[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
DoNothing(_testObjects[i]);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void RecyclableStack()
|
||||
{
|
||||
var list = new RecyclableStack<object>(_blockSize);
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Push(_testObjects[i]);
|
||||
}
|
||||
|
||||
foreach (var node in list)
|
||||
{
|
||||
DoNothing(node);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
//[Benchmark]
|
||||
public void Stack()
|
||||
{
|
||||
var list = new Stack<object>();
|
||||
for (var i = 0; i < _testObjects.LongLength; i++)
|
||||
{
|
||||
list.Push(_testObjects[i]);
|
||||
}
|
||||
|
||||
foreach (var node in list)
|
||||
{
|
||||
DoNothing(node);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum ArraySizeLimitPocBenchmarkType
|
||||
{
|
||||
ArraySizeLimit
|
||||
}
|
||||
|
||||
public class ArraySizeLimitPocBenchmarks : PocBenchmarkBase<ArraySizeLimitPocBenchmarkType>
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new ArraySizeLimitPocBenchmarks();
|
||||
benchmark.Setup();
|
||||
FindArraySizeLimit();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
[Params(2_147_483_605)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Benchmark(OperationsPerInvoke = 1)]
|
||||
public void Max_Allowed_Size_2_147_483_605()
|
||||
{
|
||||
long[] arr = ArrayPool<long>.Shared.Rent(TestObjectCount);
|
||||
DoNothing(arr);
|
||||
}
|
||||
|
||||
[Benchmark(OperationsPerInvoke = 1)]
|
||||
public static void FindArraySizeLimit()
|
||||
{
|
||||
var pool = ArrayPool<long>.Shared;
|
||||
var bufferSize = int.MaxValue / 2;
|
||||
var oldValue = 0;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.Write($"Allocating {bufferSize}...");
|
||||
var arr = pool.Rent(bufferSize);
|
||||
Console.WriteLine("success");
|
||||
pool.Return(arr);
|
||||
arr = null;
|
||||
|
||||
var nextValue = bufferSize - oldValue;
|
||||
oldValue = bufferSize;
|
||||
bufferSize = checked(bufferSize + nextValue);
|
||||
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine("error");
|
||||
var nextValue = (bufferSize - oldValue) >> 1;
|
||||
if (nextValue == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bufferSize = oldValue + nextValue;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("All done");
|
||||
throw new Exception($"Everything was successful. You can create {oldValue} byte big arrays. Exception is logged to prevent more benchmarks.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
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 BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = 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,357 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using MiscUtil;
|
||||
|
||||
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 BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = value; }
|
||||
|
||||
[Params(DelegateVsComparerPocBenchmarkType.Comparer)]
|
||||
public override DelegateVsComparerPocBenchmarkType BaselineBenchmarkType { get => base.BaselineBenchmarkType; set => base.BaselineBenchmarkType = 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) => Operator.Subtract(x, y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
private struct MyComparerStruct<T> : IComparer<T>
|
||||
{
|
||||
public int Compare(T? x, T? y) => Operator.Subtract(x, y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
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<T>(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<long>((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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
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 = 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 CalculateWithSubractWithWhileWithSse2(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 CalculateWithMixedApproachWithSubractWithWhile(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--)
|
||||
{
|
||||
CalculateWithSubractWithWhileWithSse2(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhile()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubractWithWhile(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhileAsVector()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhileAsVector(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhileWithSse2()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhileWithSse2(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithStackalloc()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithStackalloc(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithForLoopOptimized()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithForLoopOptimized(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public abstract class PocBenchmarkBase<TBenchmarkType>
|
||||
{
|
||||
public virtual TBenchmarkType? BenchmarkType { get; set; }
|
||||
public virtual TBenchmarkType? BaselineBenchmarkType { get; set; }
|
||||
|
||||
private Action? _testMethod;
|
||||
protected Action TestMethod
|
||||
{
|
||||
get => _testMethod ?? throw new OperationCanceledException("Skip - Custom benchmark run in progress");
|
||||
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(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)]
|
||||
// [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(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, RecyclableDefaults.MinItemsCountForParallelization - 1)]
|
||||
//[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, 32, 40, 50, 60, 80, 90, 100, 128)]
|
||||
// [Params(RecyclableDefaults.MinItemsCountForParallelization * 3)]
|
||||
// [Params(1_048_576)]
|
||||
public virtual int TestObjectCount { get; set; } = 1; //33_554_432; //524_288; //131_072;
|
||||
public virtual int TestObjectCountForSlowMethods => (TestObjectCount / 2) + 1;// Math.Min(TestObjectCount, 131_072);
|
||||
|
||||
//[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 => TestObjectCount switch
|
||||
{
|
||||
0 => 1,
|
||||
> 0 and <= 10_240 => TestObjectCount,
|
||||
_ => TestObjectCount / Divider > 0 ? TestObjectCount / Divider : TestObjectCount
|
||||
};
|
||||
|
||||
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 {{{BenchmarkType}}} *******");
|
||||
|
||||
if (!EqualityComparer<TBenchmarkType>.Default.Equals(BaselineBenchmarkType, default))
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP BASELINE DATA *******");
|
||||
PrepareData(BaselineBenchmarkType);
|
||||
_baselineMethod = GetTestMethod(BaselineBenchmarkType);
|
||||
}
|
||||
|
||||
//~ 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(BaselineBenchmarkType, BenchmarkType))
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP TEST CASE DATA *******");
|
||||
//~ If BaselineBenchmarkType == null, then we'll come here only if BaselineBenchmarkType != null.
|
||||
PrepareData(BenchmarkType!);
|
||||
_testMethod = GetTestMethod(BenchmarkType);
|
||||
}
|
||||
|
||||
Console.WriteLine("******* DATA PREPARED *******");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2858
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,157 @@
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Pooled;
|
||||
using Recyclable.Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum RecyclableLongListPocBenchmarkType
|
||||
{
|
||||
IndexOfV1,
|
||||
IndexOfV2,
|
||||
IndexOfV3,
|
||||
IndexOfV4,
|
||||
IndexOf_PooledList,
|
||||
IndexOf,
|
||||
EnsureCapacity_ByPowOf2,
|
||||
EnsureCapacityV1_ByPowOf2,
|
||||
EnsureCapacityV2_ByPowOf2,
|
||||
EnsureCapacityV3_ByPowOf2,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public partial class RecyclableLongListPocBenchmarks : PocBenchmarkBase<RecyclableLongListPocBenchmarkType>
|
||||
{
|
||||
[Params(RecyclableLongListPocBenchmarkType.IndexOf)]
|
||||
public override RecyclableLongListPocBenchmarkType BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = value; }
|
||||
|
||||
// [Params(BenchmarkType.Array, BenchmarkType.List, BenchmarkType.RecyclableList, BenchmarkType.RecyclableLongList)]
|
||||
[Params(RecyclableLongListPocBenchmarkType.IndexOf_PooledList)]
|
||||
public override RecyclableLongListPocBenchmarkType BaselineBenchmarkType { get => base.BaselineBenchmarkType; set => base.BaselineBenchmarkType = value; }
|
||||
|
||||
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 RecyclableLongListIndexOfV1<long>? _testRecyclableLongListIndexOfV1;
|
||||
internal RecyclableLongListIndexOfV1<long> TestObjectsAsRecyclableLongListIndexOfV1 => _testRecyclableLongListIndexOfV1 ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongListIndexOfV1<long>)} is null");
|
||||
private RecyclableLongListIndexOfV2<long>? _testRecyclableLongListIndexOfV2;
|
||||
private RecyclableLongList<long>? _testRecyclableLongList;
|
||||
internal RecyclableLongListIndexOfV2<long> TestObjectsAsRecyclableLongListIndexOfV2 => _testRecyclableLongListIndexOfV2 ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongListIndexOfV2<long>)} is null");
|
||||
private RecyclableLongListIndexOfV3<long>? _testRecyclableLongListIndexOfV3;
|
||||
internal RecyclableLongListIndexOfV3<long> TestObjectsAsRecyclableLongListIndexOfV3 => _testRecyclableLongListIndexOfV3 ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongListIndexOfV3<long>)} is null");
|
||||
private RecyclableLongListIndexOfV4<long>? _testRecyclableLongListIndexOfV4;
|
||||
internal RecyclableLongListIndexOfV4<long> TestObjectsAsRecyclableLongListIndexOfV4 => _testRecyclableLongListIndexOfV4 ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongListIndexOfV4<long>)} is null");
|
||||
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;
|
||||
private static readonly MethodInfo _ensureCapacityV1Func;
|
||||
private static readonly MethodInfo _ensureCapacityV2Func;
|
||||
private static readonly MethodInfo _ensureCapacityV3Func;
|
||||
|
||||
static RecyclableLongListPocBenchmarks()
|
||||
{
|
||||
_ensureCapacityNewFunc = typeof(RecyclableLongList<long>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList<long>)}");
|
||||
|
||||
_ensureCapacityV1Func = typeof(RecyclableLongListV1<long>).GetMethod("EnsureCapacity", BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongListV1<long>)}");
|
||||
|
||||
_ensureCapacityV2Func = typeof(RecyclableLongListV2<long>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.Public)
|
||||
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongListV2<long>)}");
|
||||
|
||||
_ensureCapacityV3Func = typeof(RecyclableLongListV3<long>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongListV3<long>)}");
|
||||
}
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new RecyclableLongListPocBenchmarks();
|
||||
benchmark.Setup();
|
||||
// benchmark.RecyclableLongList_EnsureCapacity_ByPowOf2();
|
||||
// benchmark.RecyclableLongList_EnsureCapacityV1_ByPowOf2();
|
||||
// benchmark.RecyclableLongList_EnsureCapacityV2_ByPowOf2();
|
||||
// benchmark.RecyclableLongList_EnsureCapacityV3_ByPowOf2();
|
||||
// benchmark.RecyclableLongList_EnsureCapacity_ByBlockSize();
|
||||
// benchmark.RecyclableLongList_EnsureCapacityV1_ByBlockSize();
|
||||
// benchmark.RecyclableLongList_EnsureCapacityV2_ByBlockSize();
|
||||
// benchmark.RecyclableLongList_EnsureCapacityV3_ByBlockSize();
|
||||
benchmark.RecyclableLongList_IndexOf();
|
||||
benchmark.RecyclableLongList_IndexOfV1();
|
||||
benchmark.RecyclableLongList_IndexOfV2();
|
||||
benchmark.RecyclableLongList_IndexOfV3();
|
||||
benchmark.RecyclableLongList_IndexOfV4();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
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;
|
||||
_testRecyclableLongListIndexOfV1?.Dispose();
|
||||
_testRecyclableLongListIndexOfV1 = null;
|
||||
_testRecyclableLongListIndexOfV2?.Dispose();
|
||||
_testRecyclableLongListIndexOfV2 = null;
|
||||
_testRecyclableLongListIndexOfV3?.Dispose();
|
||||
_testRecyclableLongListIndexOfV3 = null;
|
||||
_testRecyclableLongListIndexOfV4?.Dispose();
|
||||
_testRecyclableLongListIndexOfV4 = null;
|
||||
_testPooledList?.Dispose();
|
||||
_testPooledList = null;
|
||||
|
||||
base.Cleanup();
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(RecyclableLongListPocBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
RecyclableLongListPocBenchmarkType.IndexOfV1 => () => RecyclableLongList_IndexOfV1(),
|
||||
RecyclableLongListPocBenchmarkType.IndexOfV2 => () => RecyclableLongList_IndexOfV2(),
|
||||
RecyclableLongListPocBenchmarkType.IndexOfV3 => () => RecyclableLongList_IndexOfV3(),
|
||||
RecyclableLongListPocBenchmarkType.IndexOfV4 => () => RecyclableLongList_IndexOfV4(),
|
||||
RecyclableLongListPocBenchmarkType.IndexOf_PooledList => () => PooledList_IndexOf(),
|
||||
RecyclableLongListPocBenchmarkType.IndexOf => () => RecyclableLongList_IndexOf(),
|
||||
RecyclableLongListPocBenchmarkType.EnsureCapacity_ByPowOf2 => () => RecyclableLongList_EnsureCapacity_ByPowOf2(),
|
||||
RecyclableLongListPocBenchmarkType.EnsureCapacityV1_ByPowOf2 => () => RecyclableLongList_EnsureCapacityV1_ByPowOf2(),
|
||||
RecyclableLongListPocBenchmarkType.EnsureCapacityV2_ByPowOf2 => () => RecyclableLongList_EnsureCapacityV2_ByPowOf2(),
|
||||
RecyclableLongListPocBenchmarkType.EnsureCapacityV3_ByPowOf2 => () => RecyclableLongList_EnsureCapacityV3_ByPowOf2(),
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
base.PrepareData(benchmarkType);
|
||||
|
||||
switch (BenchmarkType)
|
||||
{
|
||||
case RecyclableLongListPocBenchmarkType.IndexOfV1:
|
||||
_testRecyclableLongListIndexOfV1 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount);
|
||||
break;
|
||||
case RecyclableLongListPocBenchmarkType.IndexOfV2:
|
||||
_testRecyclableLongListIndexOfV2 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount);
|
||||
break;
|
||||
case RecyclableLongListPocBenchmarkType.IndexOfV3:
|
||||
_testRecyclableLongListIndexOfV3 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount);
|
||||
break;
|
||||
case RecyclableLongListPocBenchmarkType.IndexOfV4:
|
||||
_testRecyclableLongListIndexOfV4 = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount);
|
||||
break;
|
||||
case RecyclableLongListPocBenchmarkType.IndexOf_PooledList:
|
||||
_testPooledList = new PooledList<long>(TestObjects, ClearMode.Auto);
|
||||
break;
|
||||
case RecyclableLongListPocBenchmarkType.IndexOf:
|
||||
_testRecyclableLongList = new(TestObjects, BlockSize, expectedItemsCount: TestObjectCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
BenchmarkDotNet=v0.13.3, OS=ubuntu 20.04
|
||||
Intel Xeon Platinum 8272CL CPU 2.60GHz, 1 CPU, 4 logical and 2 physical cores
|
||||
.NET SDK=7.0.203
|
||||
[Host] : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------------- |--------:|---------:|---------:|------:|--------:|
|
||||
| RecyclableLongList_IndexOfV1 | 2.274 s | 0.0447 s | 0.0894 s | 1.00 | 0.04 |
|
||||
| RecyclableLongList_IndexOfV2 | 2.302 s | 0.0456 s | 0.0750 s | 1.00 | 0.00 |
|
||||
| RecyclableLongList_IndexOf | 2.234 s | 0.0446 s | 0.0681 s | 0.97 | 0.05 |
|
||||
|
||||
// * Hints *
|
||||
Outliers
|
||||
RecyclableLongListPocBenchmarks.RecyclableLongList_IndexOfV2: Default -> 2 outliers were removed (2.54 s, 2.56 s)
|
||||
RecyclableLongListPocBenchmarks.RecyclableLongList_IndexOf: Default -> 1 outlier was detected (2.06 s)
|
||||
|
||||
// * Legends *
|
||||
Mean : Arithmetic mean of all measurements
|
||||
Error : Half of 99.9% confidence interval
|
||||
StdDev : Standard deviation of all measurements
|
||||
Ratio : Mean of the ratio distribution ([Current]/[Baseline])
|
||||
RatioSD : Standard deviation of the ratio distribution ([Current]/[Baseline])
|
||||
1 s : 1 Second (1 sec)
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum RoundBenchmarkType
|
||||
{
|
||||
MathFloor,
|
||||
MathRound,
|
||||
WithTypecasting,
|
||||
}
|
||||
|
||||
public class RoundBenchmarks : PocBenchmarkBase<RoundBenchmarkType>
|
||||
{
|
||||
[Params(RoundBenchmarkType.MathFloor)]
|
||||
public override RoundBenchmarkType BaselineBenchmarkType { get => base.BaselineBenchmarkType; set => base.BaselineBenchmarkType = value; }
|
||||
|
||||
[Params(RoundBenchmarkType.MathRound, RoundBenchmarkType.WithTypecasting)]
|
||||
public override RoundBenchmarkType BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = value; }
|
||||
|
||||
private const double OptimalParallelSearchStep = 0.329;
|
||||
|
||||
public void RoundWithMathFloor()
|
||||
{
|
||||
DoNothing((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep));
|
||||
}
|
||||
|
||||
public void RoundWithMathRound()
|
||||
{
|
||||
DoNothing((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0));
|
||||
}
|
||||
|
||||
public void RoundWithTypeCasting()
|
||||
{
|
||||
DoNothing((long)(TestObjectCount * OptimalParallelSearchStep));
|
||||
}
|
||||
|
||||
protected override Action GetTestMethod(RoundBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
RoundBenchmarkType.MathFloor => RoundWithMathFloor,
|
||||
RoundBenchmarkType.MathRound => RoundWithMathRound,
|
||||
RoundBenchmarkType.WithTypecasting => RoundWithTypeCasting,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum SpanVsArrayBenchmarkType
|
||||
{
|
||||
ArrayGetWithVar,
|
||||
ArrayGetWithField,
|
||||
SpanGet,
|
||||
ArraySetWithVar,
|
||||
ArraySetWithField,
|
||||
SpanSet
|
||||
}
|
||||
|
||||
public class SpanVsArrayBenchmarks : RecyclableBenchmarkBase<SpanVsArrayBenchmarkType>
|
||||
{
|
||||
// [Params(SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet)]
|
||||
// [Params(SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet)]
|
||||
[Params
|
||||
(
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithField, SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet
|
||||
)]
|
||||
public override SpanVsArrayBenchmarkType BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = value; }
|
||||
|
||||
[Params(SpanVsArrayBenchmarkType.ArrayGetWithField)]
|
||||
// [Params(SpanVsArrayBenchmarkType.ArraySetWithField)]
|
||||
public override SpanVsArrayBenchmarkType BaselineBenchmarkType { get => base.BaselineBenchmarkType; set => base.BaselineBenchmarkType = value; }
|
||||
|
||||
protected override Action GetTestMethod(SpanVsArrayBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithVar => ArrayGetWithVar,
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithField => ArrayGetWithField,
|
||||
SpanVsArrayBenchmarkType.SpanGet => SpanGet,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithVar => ArraySetWithVar,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithField => ArraySetWithField,
|
||||
SpanVsArrayBenchmarkType.SpanSet => SpanSet,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
public void ArrayGetWithVar()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
for (long i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void ArrayGetWithField()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
for (long i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(_testObjects![i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void SpanGet()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
Span<long> data = new(_testObjects, 0, dataCount);
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void ArraySetWithVar()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
for (long i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public void ArraySetWithField()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
for (long i = 0; i < dataCount; i++)
|
||||
{
|
||||
_testObjects![i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public void SpanSet()
|
||||
{
|
||||
var dataCount = TestObjectCount;
|
||||
Span<long> data = new(_testObjects, 0, dataCount);
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
data[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Sources;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class TaskRunVsTaskFactoryStartNewBenchmarks
|
||||
{
|
||||
public int NumberOfTasks = 100;
|
||||
private static readonly TaskFactory TaskPool = new();
|
||||
|
||||
[Benchmark]
|
||||
public void OwnTaskFactory()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
_ = TaskPool.StartNew(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskRun()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
_ = Task.Run(() => { });
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void TaskFactoryStartNew()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
_ = Task.Factory.StartNew(() => { });
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskConstructor()
|
||||
{
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
new Task(() => { }).Start();
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskConstructorWithKnownScheduler()
|
||||
{
|
||||
TaskScheduler scheduler = TaskScheduler.Current;
|
||||
for (var i = 0; i < NumberOfTasks; i++)
|
||||
{
|
||||
new Task(() => { }).Start(scheduler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using MoreLinq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum WhenParallelSearchBenchmarkType
|
||||
{
|
||||
IndexOfSequentially,
|
||||
IndexOfParallel,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class WhenParallelSearchBenchmarks : PocBenchmarkBase<WhenParallelSearchBenchmarkType>
|
||||
{
|
||||
#region ItemRange V2
|
||||
|
||||
private sealed class ItemRangeV2
|
||||
{
|
||||
public int BlockIndex;
|
||||
public long ItemsToSearchCount;
|
||||
internal bool _returned;
|
||||
|
||||
public ItemRangeV2()
|
||||
{
|
||||
}
|
||||
|
||||
public ItemRangeV2(int blockIndex, long itemsToSearchCount)
|
||||
{
|
||||
BlockIndex = blockIndex;
|
||||
ItemsToSearchCount = itemsToSearchCount;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_returned)
|
||||
{
|
||||
_returned = true;
|
||||
ItemRangePoolV2.Shared.Return(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ItemRangePoolV2
|
||||
|
||||
private static class ItemRangePoolV2
|
||||
{
|
||||
private static readonly SpinLock _updateLock = new(false);
|
||||
public static readonly ObjectPool<ItemRangeV2> Shared = new DefaultObjectPool<ItemRangeV2>(new DefaultPooledObjectPolicy<ItemRangeV2>());
|
||||
|
||||
public static ItemRangeV2 Create(int blockIndex, long itemsToSearchCount)
|
||||
{
|
||||
bool lockTaken = false;
|
||||
_updateLock.Enter(ref lockTaken);
|
||||
var itemRange = Shared.Get();
|
||||
if (lockTaken)
|
||||
{
|
||||
_updateLock.Exit(false);
|
||||
}
|
||||
|
||||
itemRange._returned = false;
|
||||
itemRange.BlockIndex = blockIndex;
|
||||
itemRange.ItemsToSearchCount = itemsToSearchCount;
|
||||
return itemRange;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//[Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32)]
|
||||
//public int NumberOfThreads { get; set; } = 3;
|
||||
|
||||
//[Params(10_000, 20_000, 35_000, 50_000, 75_000, 100_000, 125_000, 150_000, 175_000, 200_000, 225_000, 250_000, 275_000, 300_000, 325_000, 350_000, 375_000, 400_000, 500_000)]
|
||||
//[Params(320_000, 321_000, 322_000, 323_000, 324_000, 325_000, 326_000, 327_000, 328_000, 329_000, 330_000)]
|
||||
//[Params(329_000, 512_000, 750_000, 1_000_000, 3_290_000)]
|
||||
//public int Step { get; set; } = 329_000; // This was the fastest so far
|
||||
|
||||
private RecyclableLongList<long>? _testData;
|
||||
|
||||
public object? ItemToFind { get; set; }
|
||||
|
||||
[Params(WhenParallelSearchBenchmarkType.IndexOfParallel)]
|
||||
public override WhenParallelSearchBenchmarkType BenchmarkType { get => base.BenchmarkType; set => base.BenchmarkType = value; }
|
||||
|
||||
[Params(WhenParallelSearchBenchmarkType.IndexOfSequentially)]
|
||||
public override WhenParallelSearchBenchmarkType BaselineBenchmarkType { get => base.BaselineBenchmarkType; set => base.BaselineBenchmarkType = value; }
|
||||
|
||||
private long DoLongIndexOfSequentially()
|
||||
{
|
||||
// This won't work for TestObjectCount == 0
|
||||
int index;
|
||||
int blockSize = _testData!.BlockSize;
|
||||
int lastBlockWithData = _testData.LastBlockWithData;
|
||||
var memoryBlocks = _testData.AsArray;
|
||||
var itemToFind = ItemToFind;
|
||||
int blockIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
index = Array.IndexOf(memoryBlocks[blockIndex], itemToFind, 0, blockSize);
|
||||
if (index >= 0)
|
||||
{
|
||||
return (blockIndex << _testData.BlockSizePow2BitShift) + index;
|
||||
}
|
||||
|
||||
if (blockIndex + 1 < lastBlockWithData)
|
||||
{
|
||||
blockIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
index = lastBlockWithData == _testData.NextItemBlockIndex
|
||||
? Array.IndexOf(memoryBlocks[lastBlockWithData], itemToFind, 0, _testData.NextItemIndex)
|
||||
: Array.IndexOf(memoryBlocks[lastBlockWithData], itemToFind, 0, blockSize);
|
||||
|
||||
return index >= 0 ? (lastBlockWithData << _testData.BlockSizePow2BitShift) + index : -1;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
private static long DoLongIndexOfParallel(RecyclableLongList<long> list, in long itemToFind, ItemRangeV2 searchInfo, ManualResetEventSlim itemFoundSignal)
|
||||
{
|
||||
int index;
|
||||
int blockSize = list.BlockSize;
|
||||
int blockIndex = searchInfo.BlockIndex;
|
||||
long itemsToSearchCount = searchInfo.ItemsToSearchCount;
|
||||
long[][] memoryBlocks = list.AsArray;
|
||||
index = Array.IndexOf(memoryBlocks[searchInfo.BlockIndex], itemToFind, 0, blockSize);
|
||||
if (itemFoundSignal.IsSet)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (index >= 0)
|
||||
{
|
||||
return (blockIndex << list.BlockSizePow2BitShift) + index;
|
||||
}
|
||||
|
||||
itemsToSearchCount -= blockSize;
|
||||
if (itemsToSearchCount < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lastBlockWithData = blockIndex + (int)(itemsToSearchCount >> list.BlockSizePow2BitShift) + ((itemsToSearchCount & (list.BlockSize - 1)) > 0 ? 1 : 0);
|
||||
blockIndex++;
|
||||
while (true)
|
||||
{
|
||||
index = Array.IndexOf(memoryBlocks[blockIndex], itemToFind, 0, blockSize);
|
||||
if (itemFoundSignal.IsSet)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (index >= 0)
|
||||
{
|
||||
return ((long)blockIndex << list.BlockSizePow2BitShift) + index;
|
||||
}
|
||||
|
||||
itemsToSearchCount -= blockSize;
|
||||
if (blockIndex + 1 < lastBlockWithData && itemsToSearchCount < 0)
|
||||
{
|
||||
blockIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
index = itemsToSearchCount < 0 || itemFoundSignal.IsSet || lastBlockWithData > list.NextItemBlockIndex
|
||||
? -1
|
||||
: lastBlockWithData == list.NextItemBlockIndex
|
||||
? Array.IndexOf(memoryBlocks[lastBlockWithData], itemToFind, 0, checked((int)Math.Min(list.NextItemIndex, itemsToSearchCount)))
|
||||
: Array.IndexOf(memoryBlocks[lastBlockWithData], itemToFind, 0, checked((int)Math.Min(blockSize, itemsToSearchCount)));
|
||||
|
||||
return itemFoundSignal.IsSet || index < 0 ? -1 : ((long)lastBlockWithData << list.BlockSizePow2BitShift) + index;
|
||||
}
|
||||
|
||||
private long DoIndexOfParallel()
|
||||
{
|
||||
using var itemFoundSignal = new ManualResetEventSlim(false);
|
||||
using var allDoneSignal = new Barrier(1);
|
||||
//long step = Step;// TestObjectCount / NumberOfThreads;
|
||||
int blockSize = _testData!.BlockSize;
|
||||
//object[][] memoryBlocks = _testData.AsArray();
|
||||
//long itemsRemaining = testObjectCount;
|
||||
var foundItemIndex = -1L;
|
||||
var itemToFind = ItemToFind;
|
||||
//ItemRangesIterator.Iterate(0, blockSize, BlockSizePow2BitShift, TestObjectCount, (long)(TestObjectCount * 0.329), (searchInfo) =>
|
||||
//{
|
||||
// _ = allDoneSignal.AddParticipant();
|
||||
// _ = Task.Factory.StartNew((state) =>
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var index = DoLongIndexOfParallel(_testData, itemToFind, searchInfo, itemFoundSignal);
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// itemFoundSignal.Set();
|
||||
// lock (itemFoundSignal)
|
||||
// {
|
||||
// foundItemIndex = index;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// lock (allDoneSignal)
|
||||
// {
|
||||
// allDoneSignal.RemoveParticipant();
|
||||
// }
|
||||
// }
|
||||
// }, state: searchInfo);
|
||||
|
||||
// return !itemFoundSignal.IsSet;
|
||||
//});
|
||||
|
||||
//while (true)
|
||||
//{
|
||||
// var toGive = Math.Min(step, itemsRemaining);
|
||||
// SearchInfo<object> searchInfo = new(
|
||||
// blockIndex: blockIndex,
|
||||
// startingItemIndex: itemIndex,
|
||||
// itemsToSearchCount: toGive,
|
||||
// itemToFind: ItemToFind,
|
||||
// itemFoundSignal: itemFoundSignal);
|
||||
|
||||
// _ = Task.Factory.StartNew((state) =>
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var index = DoLongIndexOfParallel(_testData, (SearchInfo<object>)state!);
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// itemFoundSignal.Set();
|
||||
// lock (itemFoundSignal)
|
||||
// {
|
||||
// foundItemIndex = index;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// lock (allDoneSignal)
|
||||
// {
|
||||
// allDoneSignal.RemoveParticipant();
|
||||
// }
|
||||
// }
|
||||
// }, state: searchInfo);
|
||||
|
||||
// //itemIndex = checked((int)((itemIndex + toGive) >> BlockSizePow2BitShift)) - 1;
|
||||
// while (toGive > 0)
|
||||
// {
|
||||
// if (itemIndex + toGive < blockSize)
|
||||
// {
|
||||
// itemIndex += (int)toGive;
|
||||
// break;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// blockIndex++;
|
||||
// //itemIndex += blockSize;
|
||||
// //if (itemIndex > blockSize)
|
||||
// //{
|
||||
// // itemIndex
|
||||
// //}
|
||||
// //if (itemIndex + blockSize < )
|
||||
// //itemIndex = (int)(toGive - blockSize + itemIndex);
|
||||
// toGive -= blockSize;
|
||||
// }
|
||||
|
||||
// //if (blockIndex == _testData.LastBlockWithData)
|
||||
// //{
|
||||
// // itemIndex = checked((int)toGive);
|
||||
// // break;
|
||||
// //}
|
||||
|
||||
// }
|
||||
|
||||
// if (threadIndex + 1 < numberOfRanges && blockIndex <= _testData.LastBlockWithData)
|
||||
// {
|
||||
// threadIndex++;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
allDoneSignal.SignalAndWait();
|
||||
throw new NotImplementedException();
|
||||
return foundItemIndex;
|
||||
}
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
base.PrepareData(benchmarkType);
|
||||
|
||||
_testData ??= Enumerable.Range(1, TestObjectCount).Cast<long>().ToRecyclableLongList(BlockSize);
|
||||
ItemToFind ??= _testData.Last();
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(WhenParallelSearchBenchmarkType benchmarkType) => BenchmarkType switch
|
||||
{
|
||||
WhenParallelSearchBenchmarkType.IndexOfSequentially => IndexOfSequentially,
|
||||
WhenParallelSearchBenchmarkType.IndexOfParallel => IndexOfParallel,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_testData = default;
|
||||
base.Cleanup();
|
||||
}
|
||||
|
||||
public void IndexOfSequentially()
|
||||
{
|
||||
long index = DoLongIndexOfSequentially();
|
||||
if (index >= 0)
|
||||
{
|
||||
DoNothing(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Item not found");
|
||||
}
|
||||
}
|
||||
|
||||
public void IndexOfParallel()
|
||||
{
|
||||
var index = DoIndexOfParallel();
|
||||
if (index >= 0)
|
||||
{
|
||||
DoNothing(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Item not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
using BenchmarkDotNet.Running;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Recyclable.Collections.Benchmarks;
|
||||
using Recyclable.Collections.Benchmarks.POC;
|
||||
|
||||
BenchmarkRunner.Run<ListVsLinkedListBenchmark>();
|
||||
//BenchmarkRunner.Run<DelegateVsComparerBenchmark>();
|
||||
public class Program
|
||||
{
|
||||
static IConfig BenchmarkConfig { get; } = ManualConfig.Create(DefaultConfig.Instance).WithOptions(ConfigOptions.DisableOptimizationsValidator | ConfigOptions.JoinSummary);
|
||||
|
||||
static void RunAssemblyBenchmarks()
|
||||
{
|
||||
@@ -19,40 +22,59 @@ BenchmarkRunner.Run<ListVsLinkedListBenchmark>();
|
||||
// ****************
|
||||
// *** Template ***
|
||||
// ****************
|
||||
var benchmark = new RecyclableCollectionsBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.RecyclableLongList_IndexOf_BestAndWorstCases();
|
||||
benchmark.Cleanup();
|
||||
//var benchmark = new RecyclableCollectionsBenchmarks();
|
||||
//benchmark.Setup();
|
||||
|
||||
//foreach (var _ in Enumerable.Range(1, 1000))
|
||||
//{
|
||||
static void RunAssemblyBenchmarks()
|
||||
{
|
||||
_ = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(new[] { "-f*" });
|
||||
}
|
||||
|
||||
static void RunRecyclableCollectionsBenchmarks()
|
||||
{
|
||||
_ = BenchmarkRunner.Run<RecyclableCollectionsBenchmarks>(BenchmarkConfig);
|
||||
}
|
||||
|
||||
static void RunSelectedBenchmarks()
|
||||
{
|
||||
// ****************
|
||||
// *** Template ***
|
||||
// ****************
|
||||
var benchmark = new RecyclableCollectionsBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.RecyclableLongList_IndexOf_BestAndWorstCases();
|
||||
benchmark.Cleanup();
|
||||
|
||||
//foreach (var _ in Enumerable.Range(1, 1000))
|
||||
//{
|
||||
// benchmark.RecyclableLongList_Remove_FirstItems();
|
||||
// benchmark.RecyclableLongList_RemoveAt_LastItems();
|
||||
// benchmark.List_RemoveAt_LastItems();
|
||||
//}
|
||||
//}
|
||||
|
||||
//benchmark.Cleanup();
|
||||
}
|
||||
//benchmark.Cleanup();
|
||||
}
|
||||
|
||||
static void RunPocBenchmarks()
|
||||
{
|
||||
//_ = BenchmarkRunner.Run<BoolOrComparePocBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<DelegateVsComparerPocBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<ModuloPocBenchmarks>(BenchmarkConfig);
|
||||
// _ = BenchmarkRunner.Run<RecyclableLongListPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<RefVsInstanceMemberPocBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<WhenParallelSearchBenchmarks>(BenchmarkConfig);
|
||||
//_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||
// _ = BenchmarkRunner.Run<SpanVsArrayBenchmarks>(BenchmarkConfig);
|
||||
// ArraySizeLimitPocBenchmarks>(BenchmarkConfig);
|
||||
}
|
||||
static void RunPocBenchmarks()
|
||||
{
|
||||
_ = BenchmarkRunner.Run<BoolOrComparePocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<DelegateVsComparerPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<ModuloPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RecyclableLongListPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RefVsInstanceMemberPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<WhenParallelSearchBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<SpanVsArrayBenchmarks>(BenchmarkConfig);
|
||||
// ArraySizeLimitPocBenchmarks>(BenchmarkConfig);
|
||||
}
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
RunRecyclableCollectionsBenchmarks();
|
||||
// RunPocBenchmarks();
|
||||
// RunSelectedBenchmarks();
|
||||
// RunAssemblyBenchmarks();
|
||||
static void Main(string[] args)
|
||||
{
|
||||
RunRecyclableCollectionsBenchmarks();
|
||||
// RunPocBenchmarks();
|
||||
// RunSelectedBenchmarks();
|
||||
// RunAssemblyBenchmarks();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"profiles": {
|
||||
"WSL": {
|
||||
"commandName": "WSL2",
|
||||
"distributionName": ""
|
||||
},
|
||||
".Net": {
|
||||
"commandName": "Project",
|
||||
"nativeDebugging": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,12 @@
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.3" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
|
||||
<PackageReference Include="Collections.Pooled" Version="1.0.82" />
|
||||
<PackageReference Include="JonSkeet.MiscUtil" Version="0.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Pooled;
|
||||
using Recyclable.Collections.Benchmarks.Core;
|
||||
using Recyclable.Collections.Benchmarks.POC;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public enum RecyclableCollectionsBenchmarkSource
|
||||
{
|
||||
Unknown,
|
||||
Array,
|
||||
List,
|
||||
PooledList,
|
||||
RecyclableList,
|
||||
RecyclableLongList,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class RecyclableBenchmarkBase<TBenchmarkType> : PocBenchmarkBase<TBenchmarkType>
|
||||
{
|
||||
protected long[]? _testObjects;
|
||||
protected long[] TestObjects => _testObjects ?? throw new NullReferenceException("Something is wrong and the field is not initialized");
|
||||
|
||||
protected List<long>? _testObjectsAsList;
|
||||
protected List<long> TestObjectsAsList => _testObjectsAsList ?? throw new NullReferenceException("Something went wront and the field is not initialized");
|
||||
|
||||
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
|
||||
{
|
||||
get
|
||||
{
|
||||
for (long i = 0; i < TestObjectCount; i++)
|
||||
{
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
PrepareData(RecyclableCollectionsBenchmarkSource.Array);
|
||||
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, expectedItemsCount: 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);
|
||||
//}
|
||||
|
||||
_testObjects = default;
|
||||
_testObjectsAsList = default;
|
||||
_testObjectsAsPooledList?.Dispose();
|
||||
_testObjectsAsPooledList = default;
|
||||
_testObjectsAsRecyclableList?.Dispose();
|
||||
_testObjectsAsRecyclableList = default;
|
||||
_testObjectsAsRecyclableLongList?.Dispose();
|
||||
_testObjectsAsRecyclableLongList = default;
|
||||
base.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
//[MemoryDiagnoser]
|
||||
//public class ListVsLinkedListBenchmarks
|
||||
//{
|
||||
// [Benchmark]
|
||||
// public void RecyclableList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// using var list = new RecyclableList<object>(initialCapacity: dataCount);
|
||||
// for (long i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (long i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// [Benchmark(Baseline = true)]
|
||||
// public void RecyclableLongList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// long dataCount = TestObjectCount;
|
||||
// using var list = new RecyclableLongList<object>(BlockSize, totalItemsCount: dataCount);
|
||||
// for (long i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (long i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void List()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new List<object>(capacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(data[i]);
|
||||
// }
|
||||
|
||||
// for (var i = 0; i < list.Count; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void LinkedList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new LinkedList<object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// _ = list.AddLast(data[i]);
|
||||
// }
|
||||
|
||||
// foreach (var node in list)
|
||||
// {
|
||||
// DoNothing(node);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableQueue()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableQueue<object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.LongCount > 0)
|
||||
// {
|
||||
// DoNothing(list.Dequeue());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void Queue()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new Queue<object>(capacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.Count > 0)
|
||||
// {
|
||||
// DoNothing(list.Dequeue());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void PriorityQueue()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new PriorityQueue<object, long>(initialCapacity: dataCount);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Enqueue(data[i], i);
|
||||
// }
|
||||
|
||||
// while (list.Count > 0)
|
||||
// {
|
||||
// DoNothing(list.Dequeue());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableSortedList_InUpdateMode()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableSortedList<long, object>(BlockSize);
|
||||
// list.BeginUpdate();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
// }
|
||||
|
||||
// list.EndUpdate();
|
||||
|
||||
// for (var i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableSortedList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableSortedList<long, object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
// }
|
||||
|
||||
// for (var i = 0; i < list.LongCount; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void SortedList()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new SortedList<long, object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Add(i, data[i]);
|
||||
// }
|
||||
|
||||
// for (var i = 0; i < list.Count; i++)
|
||||
// {
|
||||
// DoNothing(list[i]);
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void RecyclableStack()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new RecyclableStack<object>(BlockSize);
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Push(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.LongCount > 0)
|
||||
// {
|
||||
// DoNothing(list.Pop());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
|
||||
// //[Benchmark]
|
||||
// public void Stack()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var dataCount = TestObjectCount;
|
||||
// var list = new Stack<object>();
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// list.Push(data[i]);
|
||||
// }
|
||||
|
||||
// while (list.Count > 0)
|
||||
// {
|
||||
// DoNothing(list.Pop());
|
||||
// }
|
||||
|
||||
// list.Clear();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|
||||
|------------------------------------------------------------ |-----------------------:|--------------------:|--------------------:|-----------------------:|-----------:|--------:|----------:|----------:|---------:|-----------:|------------:|
|
||||
|
||||
|
||||
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|
||||
|------------------------------------------------------------ |-----------:|---------:|---------:|------:|--------:|--------:|--------:|--------:|----------:|------------:|
|
||||
| Array_Create_WithCapacity | 2,447.9 us | 8.35 us | 7.40 us | 1.99 | 0.02 | 58.5938 | 58.5938 | 58.5938 | 8000061 B | 137,932.09 |
|
||||
| List_Create_WithCapacity | 2,377.6 us | 43.03 us | 40.25 us | 1.93 | 0.03 | 54.6875 | 54.6875 | 54.6875 | 8000451 B | 137,938.81 |
|
||||
| PooledList_Create_WithCapacity | 1,229.4 us | 10.70 us | 9.48 us | 1.00 | 0.00 | - | - | - | 58 B | 1.00 |
|
||||
| RecyclableList_Create_WithCapacity | 1,233.9 us | 3.93 us | 3.68 us | 1.00 | 0.01 | - | - | - | 41 B | 0.71 |
|
||||
| RecyclableLongList_Create_WithCapacity | 786.5 us | 2.32 us | 1.94 us | 0.64 | 0.01 | - | - | - | 425 B | 7.33 |
|
||||
|
||||
| List_Create | 3.5523 ns | 0.0181 ns | 0.0141 ns | 3.5476 ns | 0.000 | 0.00 | 0.0153 | - | - | 32 B | 0.000 |
|
||||
| PooledList_Create | 6.9236 ns | 0.0110 ns | 0.0098 ns | 6.9222 ns | 0.000 | 0.00 | 0.0268 | - | - | 56 B | 0.000 |
|
||||
| RecyclableList_Create | 4.6451 ns | 0.0063 ns | 0.0053 ns | 4.6457 ns | 0.000 | 0.00 | 0.0191 | - | - | 40 B | 0.000 |
|
||||
| RecyclableLongList_Create | 212.8164 ns | 11.9841 ns | 35.3355 ns | 213.2258 ns | 0.000 | 0.00 | 0.0381 | 0.0379 | - | 80 B | 0.000 |
|
||||
|
||||
Array_GetItem | 239.7 us | 0.36 us | 0.32 us | 0.66 | 0.00 | - | NA |
|
||||
List_GetItem | 363.5 us | 0.67 us | 0.56 us | 1.00 | 0.00 | - | NA |
|
||||
PooledList_GetItem | 365.3 us | 0.90 us | 0.75 us | 1.00 | 0.00 | - | NA |
|
||||
RecyclableList_GetItem | 239.2 us | 0.07 us | 0.06 us | 0.65 | 0.00 | - | NA |
|
||||
RecyclableLongList_GetItem | 538.0 us | 1.01 us | 0.89 us | 1.47 | 0.00 | 1 B | NA |
|
||||
RecyclableLongList_GetItem_AsSpan | 673.5 us | 4.85 us | 4.30 us | 1.84 | 0.01 | 1 B | NA |
|
||||
RecyclableLongList_GetItem_AsArray | 239.4 us | 0.22 us | 0.20 us | 0.66 | 0.00 | - | NA |
|
||||
RecyclableLongList_GetItem_AsForEach | 5,514.6 us | 27.28 us | 22.78 us | 15.10 | 0.06 | 109 B | NA |
|
||||
RecyclableLongList_GetItem_AsWhile | 459.3 us | 0.38 us | 0.34 us | 1.26 | 0.00 | - | NA |
|
||||
|
||||
| Array_SetItem | 2,576,086.8389 ns | 13,880.4584 ns | 11,590.8114 ns | 2,576,978.1250 ns | 2.194 | 0.01 | - | - | - | 2 B | 0.000 |
|
||||
| List_SetItem | 3,361,745.7734 ns | 98,390.1277 ns | 290,105.5114 ns | 3,505,120.8984 ns | 2.771 | 0.29 | - | - | - | 2 B | 0.000 |
|
||||
| PooledList_SetItem | 2,676,757.7524 ns | 1,228.8178 ns | 1,026.1185 ns | 2,676,991.4062 ns | 2.280 | 0.01 | - | - | - | 2 B | 0.000 |
|
||||
| RecyclableList_SetItem | 2,547,059.6540 ns | 9,002.9953 ns | 7,980.9208 ns | 2,542,056.8359 ns | 2.170 | 0.01 | - | - | - | 2 B | 0.000 |
|
||||
| RecyclableLongList_SetItem | 2,326,771.9866 ns | 3,186.0942 ns | 2,824.3895 ns | 2,326,636.7188 ns | 1.981 | 0.01 | - | - | - | 2 B | 0.000 |
|
||||
|
||||
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|
||||
|------------------------------------------------------------ |----------:|----------:|----------:|------:|--------:|---------:|--------:|--------:|-----------:|------------:|
|
||||
| List_Add | 11.002 ms | 0.2189 ms | 0.2996 ms | 1.36 | 0.04 | 140.6250 | 93.7500 | 93.7500 | 16778117 B | 236,311.51 |
|
||||
| PooledList_Add | 8.117 ms | 0.0115 ms | 0.0102 ms | 1.00 | 0.00 | - | - | - | 71 B | 1.00 |
|
||||
| RecyclableList_Add | 8.771 ms | 0.0169 ms | 0.0141 ms | 1.08 | 0.00 | - | - | - | 1233 B | 17.37 |
|
||||
| RecyclableLongList_Add | 6.024 ms | 0.1101 ms | 0.1030 ms | 0.74 | 0.01 | - | - | - | 3317 B | 46.72 |
|
||||
|
||||
| List_Add_WithCapacity | 3,724,682.0668 ns | 88,719.4866 ns | 260,198.8962 ns | 3,717,873.0469 ns | 3.326 | 0.09 | 50.7813 | 50.7813 | 50.7813 | 4000368 B | 1.000 |
|
||||
| PooledList_Add_WithCapacity | 2,575,618.8337 ns | 5,277.9410 ns | 4,678.7572 ns | 2,575,805.2734 ns | 2.194 | 0.01 | - | - | - | 60 B | 0.000 |
|
||||
| RecyclableList_Add_WithCapacity | 2,785,606.2500 ns | 4,595.4354 ns | 4,073.7338 ns | 2,785,292.7734 ns | 2.372 | 0.01 | - | - | - | 42 B | 0.000 |
|
||||
| RecyclableLongList_Add_WithCapacity | 2,878,685.9701 ns | 44,974.7609 ns | 35,113.3350 ns | 2,873,102.9297 ns | 2.453 | 0.03 | - | - | - | 170 B | 0.000 |
|
||||
|
||||
| List_AddRangeWhenSourceIsArray | 1,966,607.1581 ns | 39,075.4380 ns | 100,165.2861 ns | 1,958,457.4219 ns | 1.721 | 0.07 | 42.9688 | 42.9688 | 42.9688 | 4000364 B | 1.000 |
|
||||
| PooledList_AddRangeWhenSourceIsArray | 972,973.4049 ns | 12,365.6121 ns | 11,566.8012 ns | 974,744.8242 ns | 0.829 | 0.01 | - | - | - | 57 B | 0.000 |
|
||||
| RecyclableList_AddRangeWhenSourceIsArray | 1,098,651.7578 ns | 3,202.7829 ns | 2,995.8851 ns | 1,097,979.4922 ns | 0.936 | 0.00 | - | - | - | 41 B | 0.000 |
|
||||
| RecyclableLongList_AddRangeWhenSourceIsArray | 1,023,799.0234 ns | 2,772.1984 ns | 2,457.4816 ns | 1,023,618.7500 ns | 0.872 | 0.00 | - | - | - | 169 B | 0.000 |
|
||||
|
||||
| List_AddRangeWhenSourceIsList | 1,954,805.9462 ns | 37,631.3829 ns | 71,597.6170 ns | 1,947,531.6406 ns | 1.656 | 0.06 | 42.9688 | 42.9688 | 42.9688 | 4000363 B | 1.000 |
|
||||
| PooledList_AddRangeWhenSourceIsList | 963,657.7116 ns | 5,594.8195 ns | 5,233.3976 ns | 965,055.4199 ns | 0.820 | 0.01 | - | - | - | 57 B | 0.000 |
|
||||
| RecyclableList_AddRangeWhenSourceIsList | 1,114,697.8385 ns | 4,015.8164 ns | 3,756.3971 ns | 1,115,863.6719 ns | 0.950 | 0.00 | - | - | - | 41 B | 0.000 |
|
||||
| RecyclableLongList_AddRangeWhenSourceIsList | 1,008,424.0374 ns | 2,179.7502 ns | 1,932.2918 ns | 1,008,779.8828 ns | 0.859 | 0.00 | - | - | - | 169 B | 0.000 |
|
||||
|
||||
| List_AddRangeWhenSourceIsIList | 2,045,453.8895 ns | 40,653.4327 ns | 98,956.0738 ns | 2,040,041.7969 ns | 1.734 | 0.12 | 42.9688 | 42.9688 | 42.9688 | 4000366 B | 1.000 |
|
||||
| PooledList_AddRangeWhenSourceIsIList | 977,402.4790 ns | 4,165.1933 ns | 3,478.1251 ns | 978,420.3125 ns | 0.832 | 0.00 | - | - | - | 58 B | 0.000 |
|
||||
| RecyclableList_AddRangeWhenSourceIsIList | 1,109,563.8477 ns | 4,480.2733 ns | 4,190.8505 ns | 1,108,281.9336 ns | 0.945 | 0.00 | - | - | - | 41 B | 0.000 |
|
||||
| RecyclableLongList_AddRangeWhenSourceIsIList | 2,632,797.0052 ns | 3,899.2563 ns | 3,044.2828 ns | 2,632,267.1875 ns | 2.243 | 0.01 | - | - | - | 170 B | 0.000 |
|
||||
|
||||
| PooledList_AddRangeWhenSourceIsIEnumerable | 28,102,425.4630 ns | 556,294.1092 ns | 779,846.6478 ns | 28,009,543.7500 ns | 24.007 | 0.74 | 2187.5000 | 1375.0000 | 218.7500 | 12000526 B | 3.000 |
|
||||
| List_AddRangeWhenSourceIsIEnumerable | 47,884,030.8442 ns | 955,391.3313 ns | 1,370,193.6989 ns | 48,152,172.7273 ns | 40.578 | 1.04 | 2272.7273 | 1363.6364 | 363.6364 | 20389288 B | 5.097 |
|
||||
| RecyclableList_AddRangeWhenSourceIsIEnumerable | 27,102,237.2533 ns | 535,598.7947 ns | 595,316.6412 ns | 27,248,382.8125 ns | 23.009 | 0.61 | 2250.0000 | 1406.2500 | 250.0000 | 12000305 B | 3.000 |
|
||||
| RecyclableLongList_AddRangeWhenSourceIsIEnumerable | 27,206,882.1023 ns | 517,997.7196 ns | 636,147.7188 ns | 27,262,153.1250 ns | 23.049 | 0.64 | 2218.7500 | 1468.7500 | 250.0000 | 12000361 B | 3.000 |
|
||||
|
||||
| PooledList_AddRangeWhenSourceIsPooledList | 958,132.3033 ns | 4,444.5508 ns | 3,939.9785 ns | 957,355.9570 ns | 0.816 | 0.00 | - | - | - | 57 B | 0.000 |
|
||||
| RecyclableList_AddRangeWhenSourceIsRecyclableList | 1,068,135.4492 ns | 15,036.9473 ns | 12,556.5320 ns | 1,063,337.2070 ns | 0.910 | 0.01 | - | - | - | 41 B | 0.000 |
|
||||
| RecyclableLongList_AddRangeWhenSourceIsRecyclableList | 1,057,253.7249 ns | 2,697.5224 ns | 2,391.2834 ns | 1,057,475.9766 ns | 0.901 | 0.00 | - | - | - | 169 B | 0.000 |
|
||||
|
||||
| List_AddRange_WithCapacity | 2,022,247.3039 ns | 44,489.4467 ns | 129,071.9520 ns | 2,030,418.9453 ns | 1.767 | 0.06 | 39.0625 | 39.0625 | 39.0625 | 4000318 B | 1.000 |
|
||||
| PooledList_AddRange_WithCapacity | 965,635.9570 ns | 11,740.2154 ns | 10,981.8048 ns | 968,593.2617 ns | 0.822 | 0.01 | - | - | - | 57 B | 0.000 |
|
||||
| RecyclableList_AddRange_WithCapacity | 1,044,438.5517 ns | 3,047.5353 ns | 2,544.8300 ns | 1,045,038.8672 ns | 0.890 | 0.00 | - | - | - | 41 B | 0.000 |
|
||||
| RecyclableLongList_AddRange_WithCapacity | 1,028,953.5156 ns | 17,735.8499 ns | 14,810.2379 ns | 1,022,104.4922 ns | 0.876 | 0.01 | - | - | - | 169 B | 0.000 |
|
||||
|
||||
| Array_Count | 0.0087 ns | 0.0110 ns | 0.0103 ns | 0.0024 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
| List_Count | 1.2190 ns | 0.0046 ns | 0.0040 ns | 1.2173 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
| PooledList_Count | 0.0037 ns | 0.0015 ns | 0.0012 ns | 0.0040 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
| RecyclableList_Count | 1.2096 ns | 0.0009 ns | 0.0008 ns | 1.2092 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
| RecyclableLongList_Count | 0.0103 ns | 0.0008 ns | 0.0007 ns | 0.0102 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
|
||||
| Array_LongCount | 0.0021 ns | 0.0005 ns | 0.0004 ns | 0.0022 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
| RecyclableLongList_LongCount | 0.0030 ns | 0.0004 ns | 0.0003 ns | 0.0031 ns | 0.000 | 0.00 | - | - | - | - | 0.000 |
|
||||
|
||||
| List_Contains_FirstItems | 1,855,720,661.5385 ns | 16,632,292.4881 ns | 13,888,717.5079 ns | 1,850,307,400.0000 ns | 1,580.480 | 10.24 | - | - | - | 600 B | 0.000 |
|
||||
| PooledList_Contains_FirstItems | 1,854,542,814.2857 ns | 3,151,361.3032 ns | 2,793,599.7119 ns | 1,855,147,650.0000 ns | 1,579.345 | 5.84 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableLongList_Contains_FirstItems | 1,842,715,553.8462 ns | 5,837,438.3043 ns | 4,874,525.3630 ns | 1,840,917,300.0000 ns | 1,569.420 | 6.23 | - | - | - | 600 B | 0.000 |
|
||||
|
||||
| List_Contains_LastItems | 56,934,350,853.3333 ns | 257,718,254.2389 ns | 241,069,814.9149 ns | 56,884,611,800.0000 ns | 48,516.143 | 270.39 | - | - | - | 600 B | 0.000 |
|
||||
| PooledList_Contains_LastItems | 57,262,565,633.3333 ns | 295,685,051.7358 ns | 276,583,980.8497 ns | 57,246,796,900.0000 ns | 48,801.131 | 237.64 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableLongList_Contains_LastItems | 57,019,747,564.2857 ns | 264,241,719.1753 ns | 234,243,401.3552 ns | 57,059,345,900.0000 ns | 48,552.402 | 223.09 | - | - | - | 600 B | 0.000 |
|
||||
|
||||
| Array_IndexOf_FirstItems | 1,874,810,260.0000 ns | 25,774,115.5271 ns | 24,109,123.6555 ns | 1,867,388,700.0000 ns | 1,597.521 | 22.54 | - | - | - | 600 B | 0.000 |
|
||||
| List_IndexOf_FirstItems | 1,864,704,725.0000 ns | 10,982,470.8154 ns | 8,574,390.8164 ns | 1,866,253,200.0000 ns | 1,588.702 | 10.94 | - | - | - | 600 B | 0.000 |
|
||||
| PooledList_IndexOf_FirstItems | 1,840,856,800.0000 ns | 4,046,589.8784 ns | 3,159,311.2037 ns | 1,839,944,050.0000 ns | 1,568.374 | 6.17 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableList_IndexOf_FirstItems | 1,832,934,950.0000 ns | 1,729,308.0131 ns | 1,350,129.9476 ns | 1,832,475,300.0000 ns | 1,561.625 | 5.52 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableLongList_IndexOf_FirstItems | 1,844,986,792.3077 ns | 3,209,050.1952 ns | 2,679,702.2516 ns | 1,843,943,600.0000 ns | 1,571.359 | 6.49 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableLongList_LongIndexOf_FirstItems | 1,878,933,500.0000 ns | 17,118,131.6171 ns | 16,012,310.9355 ns | 1,870,009,600.0000 ns | 1,601.616 | 14.82 | - | - | - | 600 B | 0.000 |
|
||||
|
||||
| List_IndexOf_LastItems | 57,303,575,140.0000 ns | 297,612,744.3548 ns | 278,387,145.7216 ns | 57,391,576,000.0000 ns | 48,792.865 | 303.56 | - | - | - | 600 B | 0.000 |
|
||||
| PooledList_IndexOf_LastItems | 57,032,399,106.6667 ns | 281,241,865.3817 ns | 263,073,815.3730 ns | 56,895,992,200.0000 ns | 48,566.622 | 322.88 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableLongList_IndexOf_LastItems | 57,308,279,713.3333 ns | 272,718,905.6589 ns | 255,101,433.5602 ns | 57,297,645,400.0000 ns | 48,767.562 | 239.96 | - | - | - | 600 B | 0.000 |
|
||||
| RecyclableLongList_LongIndexOf_LastItems | 57,198,323,460.0000 ns | 282,971,632.5816 ns | 264,691,840.6850 ns | 57,198,418,300.0000 ns | 48,669.107 | 304.11 | - | - | - | 600 B | 0.000 |
|
||||
|
||||
| List_Remove_FirstItems | 5,023,030,012.5000 ns | 82,615,052.4052 ns | 107,422,903.9562 ns | 5,000,417,000.0000 ns | 4,295.171 | 116.37 | - | - | - | 4000656 B | 1.000 |
|
||||
| PooledList_Remove_FirstItems | 4,750,601,721.4286 ns | 17,989,258.8487 ns | 15,947,009.4038 ns | 4,747,622,550.0000 ns | 4,043.997 | 21.26 | - | - | - | 992 B | 0.000 |
|
||||
| RecyclableList_Remove_FirstItems | 4,950,634,900.0000 ns | 33,761,094.2570 ns | 29,928,330.6849 ns | 4,936,519,050.0000 ns | 4,218.075 | 23.90 | - | - | - | 640 B | 0.000 |
|
||||
| RecyclableLongList_Remove_FirstItems | 5,020,383,250.0000 ns | 100,209,734.5497 ns | 115,401,679.3276 ns | 5,029,163,750.0000 ns | 4,306.772 | 86.95 | - | - | - | 952 B | 0.000 |
|
||||
|
||||
| List_Remove_LastItems | 56,593,869,333.3333 ns | 258,693,958.6041 ns | 241,982,489.3835 ns | 56,513,091,800.0000 ns | 48,189.227 | 272.02 | - | - | - | 4000656 B | 1.000 |
|
||||
| PooledList_Remove_LastItems | 56,465,443,542.8571 ns | 99,443,506.1766 ns | 88,154,078.0245 ns | 56,458,364,050.0000 ns | 48,092.866 | 216.09 | - | - | - | 992 B | 0.000 |
|
||||
| RecyclableList_Remove_LastItems | 57,432,405,146.6667 ns | 264,062,625.8226 ns | 247,004,344.0307 ns | 57,409,508,000.0000 ns | 48,952.707 | 234.83 | - | - | - | 640 B | 0.000 |
|
||||
| RecyclableLongList_Remove_LastItems | 57,077,678,728.5714 ns | 210,992,675.8689 ns | 187,039,511.4398 ns | 57,038,290,150.0000 ns | 48,614.503 | 242.79 | - | - | - | 952 B | 0.000 |
|
||||
|
||||
| List_RemoveAt_FirstItems | 4,517,669,893.3333 ns | 77,360,576.7460 ns | 72,363,131.4861 ns | 4,546,302,700.0000 ns | 3,850.590 | 62.34 | - | - | - | 4000656 B | 1.000 |
|
||||
| PooledList_RemoveAt_FirstItems | 4,439,417,700.0000 ns | 40,915,112.8948 ns | 38,272,021.9874 ns | 4,418,366,400.0000 ns | 3,779.751 | 38.92 | - | - | - | 992 B | 0.000 |
|
||||
| RecyclableList_RemoveAt_FirstItems | 4,558,102,892.8571 ns | 25,076,973.8515 ns | 22,230,084.1404 ns | 4,559,174,800.0000 ns | 3,882.107 | 16.61 | - | - | - | 640 B | 0.000 |
|
||||
| RecyclableLongList_RemoveAt_FirstItems | 4,617,033,766.6667 ns | 85,061,197.3076 ns | 79,566,296.7373 ns | 4,632,994,800.0000 ns | 3,928.768 | 72.17 | - | - | - | 952 B | 0.000 |
|
||||
|
||||
| List_RemoveAt_LastItems | 2,005,211.3281 ns | 40,078.0351 ns | 84,538.1787 ns | 2,010,579.1016 ns | 1.725 | 0.08 | 42.9688 | 42.9688 | 42.9688 | 4000306 B | 1.000 |
|
||||
| PooledList_RemoveAt_LastItems | 1,047,436.1654 ns | 5,655.2027 ns | 5,289.8801 ns | 1,044,690.9180 ns | 0.892 | 0.01 | - | - | - | 58 B | 0.000 |
|
||||
| RecyclableList_RemoveAt_LastItems | 1,256,380.8969 ns | 9,142.3285 ns | 7,634.2584 ns | 1,254,354.9805 ns | 1.070 | 0.01 | - | - | - | 41 B | 0.000 |
|
||||
| RecyclableLongList_RemoveAt_LastItems | 1,621,193.5826 ns | 20,030.6198 ns | 17,756.6227 ns | 1,620,789.8438 ns | 1.379 | 0.02 | - | - | - | 353 B | 0.000 |
|
||||
Reference in new issue
Block a user