Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a00b147304 | ||
|
|
5d27fb599a | ||
|
|
0cecbe9645 | ||
|
|
97e60e381b | ||
|
|
6788c7a18c | ||
|
|
56c14910e0 | ||
|
|
8a4364e0e9 | ||
|
|
90ae27ce5d | ||
|
|
15a282de9f | ||
|
|
19775255bd | ||
|
|
c0e6f33f74 | ||
|
|
560e5e95c9 | ||
|
|
203b13268f | ||
|
|
ec69b1c406 |
No files matched your search
+1
-1
@@ -3,7 +3,7 @@ The project & source code is free for educational & personal use. **Any
|
||||
|
||||
# Donation requirements for a life-time, commercial use
|
||||
* Commercial license is paid one time.
|
||||
* It can be obtained by donaiting $10 for each developer seat, using the link provided below. If you hire 2 developers, you need to donate $20 for a life-time, commercial use of this package.
|
||||
* It can be obtained by donating $10 for each developer seat, using the link provided below. If you hire 2 developers, you need to donate $20 for a life-time, commercial use of this package.
|
||||
* Your license stays with you, if your developer moves somewhere else.
|
||||
|
||||
# Link for donations
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Add()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
var list = new long[dataCount];
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_AddRangeWhenSourceIsArray()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = new long[TestObjectCount];
|
||||
data.CopyTo(list, 0);
|
||||
}
|
||||
|
||||
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>(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);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_AddRangeWhenSourceIsIEnumerable()
|
||||
{
|
||||
var data = TestObjectsAsIEnumerable;
|
||||
var list = new long[TestObjectCount];
|
||||
int itemIndex = 0;
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
list[itemIndex++] = item;
|
||||
}
|
||||
}
|
||||
|
||||
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>(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);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_AddRangeWhenSourceIsIList()
|
||||
{
|
||||
var data = (IList<long>)TestObjectsAsRecyclableLongList;
|
||||
var list = new long[TestObjectCount];
|
||||
data.CopyTo(list, 0);
|
||||
}
|
||||
|
||||
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>)TestObjectsAsRecyclableLongList;
|
||||
using var list = new PooledList<long>(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);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_AddRangeWhenSourceIsList()
|
||||
{
|
||||
var data = TestObjectsAsList;
|
||||
var list = new long[TestObjectCount];
|
||||
data.CopyTo(list, 0);
|
||||
}
|
||||
|
||||
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>(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);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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>(TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_AddRangeWhenSourceIsRecyclableLongList()
|
||||
{
|
||||
var data = TestObjectsAsRecyclableList;
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: BlockSize, initialCapacity: TestObjectCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_AddRange_WithCapacity()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
var list = new long[dataCount];
|
||||
data.CopyTo(list, 0);
|
||||
}
|
||||
|
||||
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, initialCapacity: dataCount);
|
||||
list.AddRange(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
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, initialCapacity: dataCount);
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.Add(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.BinarySearch(list, data[i]));
|
||||
DoNothing(Array.BinarySearch(list, data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.BinarySearch(data[i]));
|
||||
DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.BinarySearch(data[i]));
|
||||
DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_BinarySearch_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.BinarySearch(data[i]));
|
||||
DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_BinarySearch_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.BinarySearch(data[i]));
|
||||
// DoNothing(list.BinarySearch(data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
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)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
DoNothing(Array.ConvertAll(list, static (item) => (long) item));
|
||||
}
|
||||
|
||||
public void List_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
DoNothing(list.ConvertAll(static (item) => (long)item));
|
||||
}
|
||||
|
||||
public void PooledList_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
using var converted = list.ConvertAll(static (item) => (long)item);
|
||||
DoNothing(converted);
|
||||
}
|
||||
|
||||
public void RecyclableList_ConvertAll()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
using RecyclableList<long> converted = list.ConvertAll(static (item) => (long)item);
|
||||
DoNothing(converted);
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_ConvertAll()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// using RecyclableList<long> converted = list.ConvertAll(static (item) => (long)item);
|
||||
// DoNothing(converted);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using Collections.Pooled;
|
||||
|
||||
#pragma warning disable CA1822, CA1825
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Create()
|
||||
{
|
||||
var list = new long[0];
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void List_Create()
|
||||
{
|
||||
var list = new List<long>();
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void PooledList_Create()
|
||||
{
|
||||
using var list = new PooledList<long>(ClearMode.Auto);
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void RecyclableList_Create()
|
||||
{
|
||||
using var list = new RecyclableList<long>();
|
||||
DoNothing(list);
|
||||
}
|
||||
|
||||
public void RecyclableLongList_Create()
|
||||
{
|
||||
using var list = new RecyclableLongList<long>();
|
||||
DoNothing(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
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, initialCapacity: TestObjectCount);
|
||||
DoNothing(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.Exists(list, (x) => x == data[i]));
|
||||
DoNothing(Array.Exists(list, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Exists((x) => x == data[i]));
|
||||
DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Exists((x) => x == data[i]));
|
||||
DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Exists_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Exists((x) => x == data[i]));
|
||||
DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_Exists_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.Exists((x) => x == data[i]));
|
||||
// DoNothing(list.Exists((x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.FindAll(list, (item) => item == data[i]));
|
||||
DoNothing(Array.FindAll(list, (item) => item == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindAll((item) => item == data[i]));
|
||||
DoNothing(list.FindAll((item) => item == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsPooledList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
var temp = list.FindAll((item) => item == data[i]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
|
||||
temp = list.FindAll((item) => item == data[^(i + 1)]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_FindAll_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
var temp = list.FindAll((item) => item == data[i]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
|
||||
temp = list.FindAll((item) => item == data[^(i + 1)]);
|
||||
DoNothing(temp);
|
||||
temp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_FindAll_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// var temp = list.FindAll((item) => item == data[i]);
|
||||
// DoNothing(temp);
|
||||
// temp.Dispose();
|
||||
|
||||
// temp = list.FindAll((item) => item == data[^(i + 1)]);
|
||||
// DoNothing(temp);
|
||||
// temp.Dispose();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_FindLastIndex_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
// Console.WriteLine($"data.Length={data.Length}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
DoNothing(Array.FindLastIndex(list, 0, (x) => x == data[i]));
|
||||
DoNothing(Array.FindLastIndex(list, 0, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_FindLastIndex_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
// Console.WriteLine($"data.Length={data.Length}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCount)}={TestObjectCount}");
|
||||
// Console.WriteLine($"{nameof(TestObjectCountForSlowMethods)}={TestObjectCountForSlowMethods}");
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[i]));
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_FindLastIndex_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[i]));
|
||||
DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_FindLastIndex_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.FindLastIndex(0, (x) => x == data[i]));
|
||||
// DoNothing(list.FindLastIndex(0, (x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_FindLast_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.FindLast(list, (x) => x == data[i]));
|
||||
DoNothing(Array.FindLast(list, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_FindLast_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindLast((x) => x == data[i]));
|
||||
DoNothing(list.FindLast((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_FindLast_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.FindLast((x) => x == data[i]));
|
||||
DoNothing(list.FindLast((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_FindLast_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.FindLast((x) => x == data[i]));
|
||||
// DoNothing(list.FindLast((x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_Find_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjects;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(Array.Find(list, (x) => x == data[i]));
|
||||
DoNothing(Array.Find(list, (x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void List_Find_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Find((x) => x == data[i]));
|
||||
DoNothing(list.Find((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_Find_BestAndWorstCases()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var list = TestObjectsAsRecyclableList;
|
||||
var dataCount = TestObjectCountForSlowMethods;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Find((x) => x == data[i]));
|
||||
DoNothing(list.Find((x) => x == data[^(i + 1)]));
|
||||
}
|
||||
}
|
||||
|
||||
// public void RecyclableLongList_Find_BestAndWorstCases()
|
||||
// {
|
||||
// var data = TestObjects;
|
||||
// var list = TestObjectsAsRecyclableLongList;
|
||||
// var dataCount = TestObjectCountForSlowMethods;
|
||||
// for (var i = 0; i < dataCount; i++)
|
||||
// {
|
||||
// DoNothing(list.Find((x) => x == data[i]));
|
||||
// DoNothing(list.Find((x) => x == data[^(i + 1)]));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public partial class RecyclableCollectionsBenchmarks
|
||||
{
|
||||
public void Array_ForEach()
|
||||
{
|
||||
foreach (var item in TestObjects)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Array_VersionedForEach()
|
||||
{
|
||||
foreach (var item in TestObjects)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void List_ForEach()
|
||||
{
|
||||
foreach (var item in TestObjectsAsList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void List_VersionedForEach()
|
||||
{
|
||||
foreach (var item in TestObjectsAsList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_ForEach()
|
||||
{
|
||||
foreach (var item in TestObjectsAsPooledList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void PooledList_VersionedForEach()
|
||||
{
|
||||
foreach (var item in TestObjectsAsPooledList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_ForEach()
|
||||
{
|
||||
foreach (var item in TestObjectsAsRecyclableList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableList_VersionedForEach()
|
||||
{
|
||||
foreach (var item in (IRecyclableVersionedList<long>)TestObjectsAsRecyclableList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_ForEach()
|
||||
{
|
||||
foreach (var item in TestObjectsAsRecyclableLongList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_VersionedForEach()
|
||||
{
|
||||
foreach (var item in (IRecyclableVersionedLongList<long>)TestObjectsAsRecyclableLongList)
|
||||
{
|
||||
DoNothing(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
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++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
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)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
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)]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public enum RecyclableCollectionsBenchmarkType
|
||||
{
|
||||
Unknown, Add_WithCapacity, Add, AddRange_WithCapacity, AddRangeWhenSourceIsArray, AddRangeWhenSourceIsIEnumerable,
|
||||
AddRangeWhenSourceIsIList, AddRangeWhenSourceIsList, AddRangeWhenSourceIsSameType, BinarySearch_BestAndWorstCases,
|
||||
Contains_FirstItems, Contains_LastItems, ConvertAll, Count, Create_WithCapacity, Create, Exists_BestAndWorstCases,
|
||||
Find_BestAndWorstCases, FindAll_BestAndWorstCases, FindLast_BestAndWorstCases, FindLastIndex_BestAndWorstCases,
|
||||
ForEach, GetItem, IndexOf_BestAndWorstCases,IndexOf_FirstItems, IndexOf_LastItems, LongCount,
|
||||
Remove_FirstItems, Remove_LastItems, RemoveAt_FirstItems, RemoveAt_LastItems,
|
||||
SetItem, VersionedForEach
|
||||
}
|
||||
|
||||
public partial class RecyclableCollectionsBenchmarks : RecyclableBenchmarkBase<RecyclableCollectionsBenchmarkSource>
|
||||
{
|
||||
public RecyclableCollectionsBenchmarks()
|
||||
{
|
||||
TestObjectCount = 1;
|
||||
//BaseDataType = RecyclableCollectionsBenchmarkSource.List;
|
||||
DataType = RecyclableCollectionsBenchmarkSource.RecyclableList;
|
||||
}
|
||||
|
||||
[Params
|
||||
(
|
||||
RecyclableCollectionsBenchmarkType.Add_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.Add,
|
||||
RecyclableCollectionsBenchmarkType.AddRange_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsArray,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsList,
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType,
|
||||
RecyclableCollectionsBenchmarkType.BinarySearch_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.Contains_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.Contains_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.ConvertAll,
|
||||
RecyclableCollectionsBenchmarkType.Count,
|
||||
RecyclableCollectionsBenchmarkType.Create_WithCapacity,
|
||||
RecyclableCollectionsBenchmarkType.Create,
|
||||
RecyclableCollectionsBenchmarkType.Exists_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.Find_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.FindAll_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.FindLast_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.FindLastIndex_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.ForEach,
|
||||
RecyclableCollectionsBenchmarkType.GetItem,
|
||||
RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases,
|
||||
RecyclableCollectionsBenchmarkType.IndexOf_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.IndexOf_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.LongCount,
|
||||
RecyclableCollectionsBenchmarkType.Remove_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.Remove_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.RemoveAt_FirstItems,
|
||||
RecyclableCollectionsBenchmarkType.RemoveAt_LastItems,
|
||||
RecyclableCollectionsBenchmarkType.SetItem,
|
||||
RecyclableCollectionsBenchmarkType.VersionedForEach
|
||||
)]
|
||||
|
||||
public RecyclableCollectionsBenchmarkType TestCase { get; set; } = RecyclableCollectionsBenchmarkType.IndexOf_BestAndWorstCases;
|
||||
|
||||
[Params
|
||||
(
|
||||
RecyclableCollectionsBenchmarkSource.List
|
||||
)]
|
||||
public override RecyclableCollectionsBenchmarkSource BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params
|
||||
(
|
||||
RecyclableCollectionsBenchmarkSource.Array,
|
||||
RecyclableCollectionsBenchmarkSource.List,
|
||||
RecyclableCollectionsBenchmarkSource.PooledList,
|
||||
RecyclableCollectionsBenchmarkSource.RecyclableList,
|
||||
RecyclableCollectionsBenchmarkSource.RecyclableLongList
|
||||
)]
|
||||
public override RecyclableCollectionsBenchmarkSource DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
protected override Action? GetTestMethod(RecyclableCollectionsBenchmarkSource benchmarkType)
|
||||
=> TestCase switch
|
||||
{
|
||||
RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType => (Action?)GetType().GetMethod($"{benchmarkType}_AddRangeWhenSourceIs{benchmarkType}", BindingFlags.Instance | BindingFlags.Public)?.CreateDelegate(typeof(Action), this),
|
||||
_ => (Action?) GetType().GetMethod($"{benchmarkType}_{TestCase}", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)?.CreateDelegate(typeof(Action), this) ?? throw new InvalidOperationException($"Method {benchmarkType}_{TestCase} not found in class {GetType().FullName}")
|
||||
};
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
switch(TestCase)
|
||||
{
|
||||
case RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsIList:
|
||||
PrepareData(RecyclableCollectionsBenchmarkSource.RecyclableLongList);
|
||||
break;
|
||||
|
||||
case RecyclableCollectionsBenchmarkType.AddRangeWhenSourceIsSameType:
|
||||
PrepareData(RecyclableCollectionsBenchmarkSource.RecyclableList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
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(0);
|
||||
}
|
||||
}
|
||||
|
||||
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(0);
|
||||
}
|
||||
}
|
||||
|
||||
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(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecyclableLongList_RemoveAt_FirstItems()
|
||||
{
|
||||
var data = TestObjects;
|
||||
using var list = new RecyclableLongList<long>(data, minBlockSize: BlockSize, initialCapacity: base.TestObjectCount);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
list.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
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, initialCapacity: base.TestObjectCount);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||
{
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
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, initialCapacity: base.TestObjectCount);
|
||||
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||
for (var i = 0; i < dataCount; i++)
|
||||
{
|
||||
DoNothing(list.Remove(data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
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, initialCapacity:base.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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace Recyclable.Collections.Benchmarks.Core
|
||||
{
|
||||
public static class DataGenerator
|
||||
{
|
||||
public static long[] EnumerateTestObjects(long testObjectCount)
|
||||
{
|
||||
var result = new long[testObjectCount];
|
||||
Console.WriteLine("******* TEST DATA ARRAY CREATED *******");
|
||||
|
||||
Span<long> resultSpan = result;
|
||||
for (int i = 0; i < testObjectCount; i++)
|
||||
{
|
||||
resultSpan[i] = i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum BoolOrComparePocBenchmarkType
|
||||
{
|
||||
Bool,
|
||||
Compare,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class BoolOrComparePocBenchmarks : PocBenchmarkBase<BoolOrComparePocBenchmarkType>
|
||||
{
|
||||
[Params(BoolOrComparePocBenchmarkType.Bool, BoolOrComparePocBenchmarkType.Compare)]
|
||||
public override BoolOrComparePocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(8)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Params(true)]
|
||||
public bool TestBool = true;
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new BoolOrComparePocBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Bool();
|
||||
benchmark.Compare();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
public void Bool()
|
||||
{
|
||||
if (TestBool)
|
||||
{
|
||||
DoNothing(TestBool);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoNothing(TestBool);
|
||||
}
|
||||
}
|
||||
|
||||
public void Compare()
|
||||
{
|
||||
if (TestObjectCount >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
DoNothing(TestBool);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoNothing(TestBool);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(BoolOrComparePocBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
BoolOrComparePocBenchmarkType.Bool => Bool,
|
||||
BoolOrComparePocBenchmarkType.Compare => Compare,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum DelegateVsComparerPocBenchmarkType
|
||||
{
|
||||
Comparer,
|
||||
Delegate,
|
||||
Func,
|
||||
ListOfBoxedStructs,
|
||||
ListOfClasses,
|
||||
ListOfComparers,
|
||||
ListOfDelegates,
|
||||
ListOfFuncs,
|
||||
ListOfLocalFuncs,
|
||||
ListOfStructs,
|
||||
ListOfUnboxedReadOnlyStructs,
|
||||
ListOfUnboxedStructs,
|
||||
StaticFunc,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class DelegateVsComparerPocBenchmarks : PocBenchmarkBase<DelegateVsComparerPocBenchmarkType>
|
||||
{
|
||||
[Params
|
||||
(
|
||||
DelegateVsComparerPocBenchmarkType.Delegate,
|
||||
DelegateVsComparerPocBenchmarkType.Func,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfClasses,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfComparers,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfDelegates,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfFuncs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfStructs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfUnboxedReadOnlyStructs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfUnboxedStructs,
|
||||
DelegateVsComparerPocBenchmarkType.StaticFunc
|
||||
)]
|
||||
public override DelegateVsComparerPocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(DelegateVsComparerPocBenchmarkType.Comparer)]
|
||||
public override DelegateVsComparerPocBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
#region Dummy classes
|
||||
|
||||
private delegate T Compare<T>(T x, T y);
|
||||
|
||||
public readonly struct MyComparerReadOnlyStruct<T> : IComparer<T>
|
||||
{
|
||||
public int Compare(T? x, T? y) => Comparer<T>.Default.Compare(x, y);
|
||||
}
|
||||
|
||||
private struct MyComparerStruct<T> : IComparer<T>
|
||||
{
|
||||
public readonly int Compare(T? x, T? y) => Comparer<T>.Default.Compare(x, y);
|
||||
}
|
||||
|
||||
private class MyComparer : IComparer<long>
|
||||
{
|
||||
public int Compare(long x, long y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new DelegateVsComparerPocBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Comparer();
|
||||
benchmark.Delegate();
|
||||
benchmark.Func();
|
||||
benchmark.ListOfBoxedStructs();
|
||||
benchmark.ListOfClasses();
|
||||
benchmark.ListOfComparers();
|
||||
benchmark.ListOfDelegates();
|
||||
benchmark.ListOfFuncs();
|
||||
benchmark.ListOfLocalFuncs();
|
||||
benchmark.ListOfStructs();
|
||||
benchmark.ListOfUnboxedReadOnlyStructs();
|
||||
benchmark.ListOfUnboxedStructs();
|
||||
benchmark.StaticFunc();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
private static readonly Comparer<long> _comparer = Comparer<long>.Default;
|
||||
private IEnumerable<long>? _testObjects;
|
||||
private IEnumerable<Func<long, long, int>>? _testListOfFunctions;
|
||||
private IEnumerable<IComparer<long>>? _testListOfComparers;
|
||||
private IEnumerable<Compare<long>>? _testListOfDelegates;
|
||||
private IEnumerable<Func<long, long, int>>? _testListOfLocalFunctions;
|
||||
private IEnumerable<MyComparer>? _testListOfClasses;
|
||||
private IEnumerable<MyComparerStruct<long>>? _testListOfStructs;
|
||||
private IEnumerable<IComparer<long>>? _testListOfBoxedStructs;
|
||||
private IEnumerable<TComparer> TestListOfUnboxedStructs<TComparer, TValue>() where TComparer : IComparer<TValue>, new()
|
||||
{
|
||||
foreach (var _ in _testObjects!)
|
||||
{
|
||||
yield return new TComparer();
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<Func<long, long, int>> GetLocalFunctions(IEnumerable<long> testObjects)
|
||||
{
|
||||
static int compareFunc(long x, long y)
|
||||
{
|
||||
return (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var _ in testObjects)
|
||||
{
|
||||
yield return compareFunc;
|
||||
}
|
||||
}
|
||||
|
||||
private void TestWithComparer(IComparer<long> comparer)
|
||||
{
|
||||
var testData = _testObjects!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = comparer.Compare(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void TestWithDelegate(Compare<long> compareFunc)
|
||||
{
|
||||
var testData = _testObjects!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void TestWithFunc(Func<long, long, int> compareFunc)
|
||||
{
|
||||
var testData = _testObjects!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||
{
|
||||
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
public void Comparer()
|
||||
{
|
||||
TestWithComparer(_comparer);
|
||||
}
|
||||
|
||||
public void Func()
|
||||
{
|
||||
TestWithFunc((x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
public void StaticFunc()
|
||||
{
|
||||
TestWithFunc(static (x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
public void Delegate()
|
||||
{
|
||||
TestWithDelegate((x, y) => (x - y) switch
|
||||
{
|
||||
> 0 => 1,
|
||||
< 0 => -1,
|
||||
_ => 0
|
||||
});
|
||||
}
|
||||
|
||||
public void ListOfFuncs()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfFunctions!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var compareFunc = testData[itemIdx];
|
||||
_ = compareFunc(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfLocalFuncs()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfLocalFunctions!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var compareFunc = testData[itemIdx];
|
||||
_ = compareFunc(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfComparers()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfComparers!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfClasses()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfClasses!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfStructs()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfStructs!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfBoxedStructs()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfBoxedStructs!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfUnboxedStructs()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = TestListOfUnboxedStructs<MyComparerStruct<long>, long>().ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfUnboxedReadOnlyStructs()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = TestListOfUnboxedStructs<MyComparerReadOnlyStruct<long>, long>().ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var comparer = testData[itemIdx];
|
||||
_ = comparer.Compare(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ListOfDelegates()
|
||||
{
|
||||
const long x = 2, y = 5;
|
||||
var testData = _testListOfDelegates!.ToArray();
|
||||
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||
{
|
||||
var compareDelegate = testData[itemIdx];
|
||||
_ = compareDelegate(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(DelegateVsComparerPocBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
DelegateVsComparerPocBenchmarkType.Comparer => Comparer,
|
||||
DelegateVsComparerPocBenchmarkType.Delegate => Delegate,
|
||||
DelegateVsComparerPocBenchmarkType.Func => Func,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs => ListOfBoxedStructs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfClasses => ListOfClasses,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfComparers => ListOfComparers,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfDelegates => ListOfDelegates,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfFuncs => ListOfFuncs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs => ListOfLocalFuncs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfStructs => ListOfStructs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfUnboxedReadOnlyStructs => ListOfUnboxedReadOnlyStructs,
|
||||
DelegateVsComparerPocBenchmarkType.ListOfUnboxedStructs => ListOfUnboxedStructs,
|
||||
DelegateVsComparerPocBenchmarkType.StaticFunc => StaticFunc,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP COMMON TEST DATA *******");
|
||||
_testObjects = Enumerable.Range(1, TestObjectCount).Select(x => (long)x);
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_testObjects = null;
|
||||
base.Cleanup();
|
||||
}
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
switch (benchmarkType)
|
||||
{
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfBoxedStructs:
|
||||
_testListOfBoxedStructs = _testObjects!.Select(_ => (IComparer<long>)new MyComparerStruct<long>());
|
||||
break;
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfClasses:
|
||||
_testListOfClasses = _testObjects!.Select(_ => new MyComparer());
|
||||
break;
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfComparers:
|
||||
_testListOfComparers = _testObjects!.Select(_ => (IComparer<long>)new MyComparer());
|
||||
break;
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfDelegates:
|
||||
_testListOfDelegates = _testObjects!.Select(_ => new Compare<long>((x, y) => new MyComparer().Compare(x, y)));
|
||||
break;
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfFuncs:
|
||||
_testListOfFunctions = _testObjects!.Select<long, Func<long, long, int>>(static _ => new MyComparer().Compare);
|
||||
break;
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfLocalFuncs:
|
||||
_testListOfLocalFunctions = GetLocalFunctions(_testObjects!);
|
||||
break;
|
||||
case DelegateVsComparerPocBenchmarkType.ListOfStructs:
|
||||
_testListOfStructs = _testObjects!.Select(_ => new MyComparerStruct<long>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using FluentAssertions;
|
||||
using Recyclable.CollectionsTests;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
|
||||
public class EqualVsContainsInConsecutiveOrderBenchmarks : IDisposable
|
||||
{
|
||||
private const int TestItemsCount = 10000;
|
||||
|
||||
private readonly IEnumerable<long> _list1 = RecyclableLongListTestData.CreateTestData(TestItemsCount).ToRecyclableList();
|
||||
private readonly IEnumerable<long> _list2 = RecyclableLongListTestData.CreateTestData(TestItemsCount).ToArray();
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void Equal()
|
||||
{
|
||||
_ = _list1.Should().Equal(_list2);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ContainsInConsecutiveOrder()
|
||||
{
|
||||
_ = _list1.Should().ContainInConsecutiveOrder(_list2);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_list1 is IDisposable disposable1)
|
||||
{
|
||||
disposable1.Dispose();
|
||||
}
|
||||
|
||||
if (_list2 is IDisposable disposable2)
|
||||
{
|
||||
disposable2.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#pragma warning disable CA1822
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public class GreaterOperatorVsDoesntEqualOperatorBenchmarks
|
||||
{
|
||||
private static readonly long num = RecyclableDefaults.MinItemsCountForParallelization;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
Console.WriteLine($"*** We're comparing if {num} is < 0 ***");
|
||||
}
|
||||
|
||||
public void Cleanup() { }
|
||||
|
||||
#pragma warning disable RCS1163, IDE0060
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void DoNothing<T>(T item)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma warning restore RCS1163
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void CompareWithGreater()
|
||||
{
|
||||
DoNothing(num > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithGreaterEqual()
|
||||
{
|
||||
DoNothing(num >= 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithDoesntEqual()
|
||||
{
|
||||
DoNothing(num != 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithLess()
|
||||
{
|
||||
DoNothing(num < 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithEqual()
|
||||
{
|
||||
DoNothing(num == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#pragma warning disable CA1822
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public class LessOperatorVsAndOperatorBenchmarks
|
||||
{
|
||||
private const int bitShift = 1 << 31;
|
||||
private static readonly Random _rnd = new(1);
|
||||
private static int num = -Math.Abs(_rnd.Next());
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
num = -1;
|
||||
Console.WriteLine($"*** We're comparing if {num} is < 0 ***");
|
||||
}
|
||||
|
||||
public void Cleanup() { }
|
||||
|
||||
#pragma warning disable RCS1163, IDE0060
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void DoNothing<T>(T item)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma warning restore RCS1163
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void CompareWithLess()
|
||||
{
|
||||
DoNothing(num < 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithAnd()
|
||||
{
|
||||
DoNothing((num & bitShift) != 0);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareWithEqual()
|
||||
{
|
||||
DoNothing(num == -1);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CompareToZero()
|
||||
{
|
||||
DoNothing(num == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,376 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
#pragma warning disable xUnit1026, RCS1163, IDE0060
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class ModuloPocBenchmarks
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new ModuloPocBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.AddWithFor();
|
||||
benchmark.AddWithForOptimized();
|
||||
benchmark.DividerAndModulusWithOperator();
|
||||
benchmark.MathDivRem();
|
||||
benchmark.MixedApproachWithForLoopOptimized();
|
||||
benchmark.MixedApproachWithSubtractWithStackalloc();
|
||||
benchmark.MixedApproachWithSubtractWithWhile();
|
||||
benchmark.MixedApproachWithSubtractWithWhileAsVector();
|
||||
benchmark.MixedApproachWithSubtractWithWhileWithSse2();
|
||||
benchmark.SubtractWithWhile();
|
||||
benchmark.SubtractWithWhileWithSse2();
|
||||
benchmark.XDivYMulX();
|
||||
benchmark.XDivYMulXWithLocalVar();
|
||||
}
|
||||
|
||||
private long _cutoff;
|
||||
private Vector128<long> _increment;
|
||||
private long _lastCaseIndex;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_cutoff = checked((long)BlockSize << 4);
|
||||
_increment = Vector128.Create(-BlockSize, 1L);
|
||||
_lastCaseIndex = 0;
|
||||
}
|
||||
|
||||
private static void DoNothing<T>(T result, T remainder, [CallerMemberName] string? callerName = null)
|
||||
{
|
||||
//Console.WriteLine($"{callerName}: result = {result}, remainder = {remainder}");
|
||||
}
|
||||
|
||||
//[Params(123, 10, 2, int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 10, int.MaxValue / 15, int.MaxValue / 20)]
|
||||
[Params(int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 8, int.MaxValue / 10, int.MaxValue / 100)]
|
||||
//[Params(int.MaxValue / 10, int.MaxValue / 20, int.MaxValue / 100)]
|
||||
public int BlockSize { get; set; } = int.MaxValue;
|
||||
|
||||
[Params(int.MaxValue, int.MaxValue / 1000, int.MaxValue / 10000)]
|
||||
//[Params(int.MaxValue)]
|
||||
//[Params(int.MaxValue * 100L)]
|
||||
public long TestNumber { get; set; } = int.MaxValue;
|
||||
|
||||
private void CalculateDividerAndModulusWithOperator(long i)
|
||||
{
|
||||
DoNothing(i / BlockSize, i % BlockSize);
|
||||
}
|
||||
|
||||
private void CalculateWithMathDivRem(long i)
|
||||
{
|
||||
DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
|
||||
private void CalculateWithAddWithFor(long i)
|
||||
{
|
||||
int result = 0;
|
||||
int remainder = 0;
|
||||
int blockSize = BlockSize;
|
||||
for (long iteration = 0; iteration < i; iteration++)
|
||||
{
|
||||
if (remainder > blockSize - 1)
|
||||
{
|
||||
remainder = 0;
|
||||
result++;
|
||||
}
|
||||
|
||||
remainder++;
|
||||
}
|
||||
|
||||
DoNothing(result, remainder);
|
||||
}
|
||||
|
||||
private void CalculateWithAddWithForOptimized(long i)
|
||||
{
|
||||
long total = 0;
|
||||
int result = 0;
|
||||
int blockSize = BlockSize;
|
||||
while (total + blockSize <= i)
|
||||
{
|
||||
total += blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing(result, i - total);
|
||||
}
|
||||
|
||||
private void CalculateWithXDivYMulX(long i)
|
||||
{
|
||||
DoNothing(i / BlockSize, i - (i / BlockSize * BlockSize));
|
||||
}
|
||||
|
||||
private void CalculateWithXDivYMulXWithLocalVar(long i)
|
||||
{
|
||||
int blockSize = BlockSize;
|
||||
int result = (int)(i / blockSize);
|
||||
DoNothing(result, i - (result * blockSize));
|
||||
}
|
||||
|
||||
private void CalculateWithSubtractWithWhile(long i)
|
||||
{
|
||||
int result = 0;
|
||||
long remainder = i;
|
||||
int blockSize = BlockSize;
|
||||
while (remainder >= blockSize)
|
||||
{
|
||||
remainder -= blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing(result, remainder);
|
||||
}
|
||||
|
||||
private void CalculateWithSubtractWithWhileWithSse2(long i)
|
||||
{
|
||||
var state = Vector128.Create(i, 0);
|
||||
int blockSize = BlockSize;
|
||||
var inc = _increment;
|
||||
while (state.GetElement(0) >= blockSize)
|
||||
{
|
||||
state = Sse2.Add(state, inc);
|
||||
}
|
||||
|
||||
DoNothing(state.GetElement(1), state.GetElement(0));
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithWhile(long i)
|
||||
{
|
||||
long remainder;
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing(Math.DivRem(i, BlockSize, out remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
int result = 0;
|
||||
int blockSize = BlockSize;
|
||||
remainder = i;
|
||||
while (remainder >= blockSize)
|
||||
{
|
||||
remainder -= blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing(result, remainder);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithWhileAsVector(long i)
|
||||
{
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var state = new Vector<long>(new[] { 0L, i, 0, 0 });
|
||||
var increment = new Vector<long>(new[] { 1L, -BlockSize, 0, 0 });
|
||||
int blockSize = BlockSize;
|
||||
while (state[1] >= blockSize)
|
||||
{
|
||||
state += increment;
|
||||
}
|
||||
|
||||
DoNothing(state[0], state[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithWhileWithSse2(long i)
|
||||
{
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
var increment = _increment;
|
||||
var state = Vector128.Create(i, 0);
|
||||
int blockSize = BlockSize;
|
||||
while (state.GetElement(0) >= blockSize)
|
||||
{
|
||||
state = Sse2.Add(state, increment);
|
||||
}
|
||||
|
||||
DoNothing(state.GetElement(1), state.GetElement(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithSubtractWithStackalloc(long i)
|
||||
{
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<long> state = stackalloc long[2] { i, 0 };// Vector128.Create(BlockSize, 0);
|
||||
int blockSize = BlockSize;
|
||||
while (state[0] >= blockSize)
|
||||
{
|
||||
state[0] -= blockSize;
|
||||
state[1]++;
|
||||
}
|
||||
|
||||
DoNothing(state[1], state[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateWithMixedApproachWithForLoopOptimized(long i)
|
||||
{
|
||||
long total;
|
||||
if (i >= _cutoff)
|
||||
{
|
||||
DoNothing(Math.DivRem(i, BlockSize, out total), total);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = 0;
|
||||
int result = 0;
|
||||
int blockSize = BlockSize;
|
||||
while (total + blockSize <= i)
|
||||
{
|
||||
total += blockSize;
|
||||
result++;
|
||||
}
|
||||
|
||||
DoNothing(result, i - total);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void DividerAndModulusWithOperator()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateDividerAndModulusWithOperator(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void MathDivRem()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMathDivRem(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void AddWithFor()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithAddWithFor(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void AddWithForOptimized()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithAddWithForOptimized(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void XDivYMulX()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithXDivYMulX(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void XDivYMulXWithLocalVar()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithXDivYMulXWithLocalVar(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SubtractWithWhile()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithSubtractWithWhile(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SubtractWithWhileWithSse2()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithSubtractWithWhileWithSse2(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhile()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhile(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhileAsVector()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhileAsVector(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithWhileWithSse2()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithWhileWithSse2(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithSubtractWithStackalloc()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithSubtractWithStackalloc(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void MixedApproachWithForLoopOptimized()
|
||||
{
|
||||
long testNumber = TestNumber;
|
||||
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||
{
|
||||
CalculateWithMixedApproachWithForLoopOptimized(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public abstract class PocBenchmarkBase<TBenchmarkType>
|
||||
{
|
||||
public virtual TBenchmarkType? DataType { get; set; }
|
||||
public virtual TBenchmarkType? BaseDataType { get; set; }
|
||||
|
||||
private Action? _testMethod;
|
||||
protected Action TestMethod
|
||||
{
|
||||
get => _testMethod ?? throw new OperationCanceledException("Skip - No actual defined");
|
||||
set => _testMethod = value;
|
||||
}
|
||||
|
||||
private Action? _baselineMethod;
|
||||
protected Action BaselineMethod
|
||||
{
|
||||
get => _baselineMethod ?? throw new OperationCanceledException("Skip - No baseline defined");
|
||||
set => _baselineMethod = value;
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void Baseline() => BaselineMethod.Invoke();
|
||||
|
||||
[Benchmark]
|
||||
public void Actual() => TestMethod.Invoke();
|
||||
|
||||
// 0 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524_288
|
||||
// 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912
|
||||
// 1073741824 2147483648
|
||||
|
||||
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)]
|
||||
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)]
|
||||
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 100_000_000)]
|
||||
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 850_000 - 1, 1_000_000, RecyclableDefaults.MaxPooledBlockSize)]
|
||||
// [Params(1_000_000, 10_000_000, 100_000_000, 1_000_000_000)]
|
||||
// [Params(1, 10, 64, 128, 192, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144)]
|
||||
// [Params(524_288, 786_432, 1_048_576)]
|
||||
// [Params(262_144, 393_216, 524_288)]
|
||||
// [Params(850_000_000)]
|
||||
// [Params(100_000_000)]
|
||||
// [Params(RecyclableDefaults.MinItemsCountForParallelization)]
|
||||
// [Params(127)]
|
||||
// [Params(16)]
|
||||
// [Params(10, 15, 128)]
|
||||
// [Params(1)]
|
||||
// [Params(RecyclableDefaults.MaxPooledBlockSize)]
|
||||
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 10_000_000, 33_554_432, 50_000_000, 100_000_000)]
|
||||
// *** [Params(RecyclableDefaults.MinPooledArrayLength - 3, RecyclableDefaults.MinPooledArrayLength - 2, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 2, RecyclableDefaults.MinPooledArrayLength + 3)]
|
||||
[Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||
// *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||
// [Params(256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||
// [Params(RecyclableDefaults.MinItemsCountForParallelization, 1_048_576, 2_097_152, 4_194_304, 8_388_608, 16_777_216, 33_554_432, RecyclableDefaults.MaxPooledBlockSize)]
|
||||
// *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 64, 70, 80, 90, 100, 127, 128)]
|
||||
// [Params(1, 10, 1024, 10240, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||
// [Params(RecyclableDefaults.MinItemsCountForParallelization * 3)]
|
||||
// [Params(1_048_576)]
|
||||
public virtual int TestObjectCount { get; set; } = 0; //8_192;//131_072; //1; //33_554_432; //524_288; //131_072;
|
||||
public virtual int TestObjectCountForSlowMethods { get; private set; }
|
||||
|
||||
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200)]
|
||||
// [Params(10, 20, 50, 100)]
|
||||
// [Params(1, 10)]
|
||||
public int Divider = 10;
|
||||
//public int BlockSize = 1_048_576;//int.MaxValue - 1;
|
||||
public int BlockSize { get; private set; }
|
||||
|
||||
public byte BlockSizePow2BitShift => checked((byte)(31 - BitOperations.LeadingZeroCount((uint)BlockSize)));
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
protected static void DoNothing<T>(in T item)
|
||||
{
|
||||
_ = item;
|
||||
}
|
||||
|
||||
protected static Exception CreateUnknownBenchmarkTypeException<T>(T benchmarkType)
|
||||
{
|
||||
return new InvalidOperationException($"******* UNKNOWN BENCHMARK TYPE {{{benchmarkType}}} *******");
|
||||
}
|
||||
|
||||
protected static Exception CreateMethodNotFoundException(in string methodName, in string? className)
|
||||
{
|
||||
return new MethodAccessException($"******* METHOD {{{methodName}}} NOT FOUND IN CLASS {{{className}}} *******");
|
||||
}
|
||||
|
||||
protected virtual void PrepareData<T>(T benchmarkType) { }
|
||||
protected virtual Action? GetTestMethod(TBenchmarkType? benchmarkType) => null;
|
||||
|
||||
[GlobalCleanup]
|
||||
public virtual void Cleanup()
|
||||
{
|
||||
_baselineMethod = null;
|
||||
_testMethod = null;
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public virtual void Setup()
|
||||
{
|
||||
Console.WriteLine($"******* SETTING UP TEST CASE FOR BENCHMARK {{{DataType}}} *******");
|
||||
|
||||
TestObjectCountForSlowMethods = (TestObjectCount / 2) + 1;
|
||||
|
||||
BlockSize = TestObjectCount switch
|
||||
{
|
||||
0 => 1,
|
||||
> 0 and <= 10_240 => TestObjectCount,
|
||||
_ => TestObjectCount / Divider > 0 ? TestObjectCount / Divider : TestObjectCount
|
||||
};
|
||||
|
||||
if (BlockSize > 0)
|
||||
{
|
||||
BlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)BlockSize));
|
||||
}
|
||||
|
||||
Console.WriteLine($"******* BaseDataType = {BaseDataType}; default = {default(TBenchmarkType)} *******");
|
||||
|
||||
if (!EqualityComparer<TBenchmarkType>.Default.Equals(BaseDataType, default))
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP BASELINE DATA *******");
|
||||
PrepareData(BaseDataType);
|
||||
_baselineMethod = GetTestMethod(BaseDataType);
|
||||
}
|
||||
|
||||
//~ We don't want to prepare data if baseline data is the same is benchmark data.
|
||||
//~ One would override another - waste of time & resources.
|
||||
if (!EqualityComparer<TBenchmarkType>.Default.Equals(BaseDataType, DataType))
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP TEST CASE DATA *******");
|
||||
//~ If BaseDataType == null, then we'll come here only if DataType != null.
|
||||
PrepareData(DataType!);
|
||||
_testMethod = GetTestMethod(DataType);
|
||||
}
|
||||
|
||||
Console.WriteLine("******* DATA PREPARED *******");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Collections.Pooled;
|
||||
using Recyclable.Collections.Benchmarks.Core;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public partial class RecyclableLongListPocBenchmarks<T> : PocBenchmarkBase<T>
|
||||
{
|
||||
private long[]? _testArray;
|
||||
public long[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null");
|
||||
|
||||
public RecyclableLongList<long> TestObjectsAsRecyclableLongList => _testRecyclableLongList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongList<long>)} is null");
|
||||
private RecyclableLongList<long>? _testRecyclableLongList;
|
||||
private PooledList<long>? _testPooledList;
|
||||
internal PooledList<long> TestPooledList => _testPooledList ?? throw new NullReferenceException($"Something is wrong and {nameof(PooledList<long>)} is null");
|
||||
|
||||
private static readonly MethodInfo _ensureCapacityNewFunc;
|
||||
|
||||
static RecyclableLongListPocBenchmarks()
|
||||
{
|
||||
_ensureCapacityNewFunc = typeof(RecyclableLongList<long>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList<long>)}");
|
||||
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
Console.WriteLine("******* SETTING UP EXPECTED RESULTS DATA *******");
|
||||
_testArray = DataGenerator.EnumerateTestObjects(TestObjectCount);
|
||||
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_testArray = null;
|
||||
_testRecyclableLongList?.Dispose();
|
||||
_testRecyclableLongList = null;
|
||||
_testPooledList?.Dispose();
|
||||
_testPooledList = null;
|
||||
|
||||
base.Cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
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)
|
||||
|
||||
@@ -1,364 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
#pragma warning disable RCS1085
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public class RefVsInstanceMemberPocBenchmarks
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new RefVsInstanceMemberPocBenchmarks();
|
||||
benchmark.ArrayInstanceMember2();
|
||||
benchmark.ArrayInstanceMember3();
|
||||
benchmark.ArrayInstanceMember4();
|
||||
benchmark.ArrayInstanceMember5();
|
||||
benchmark.ArrayInstanceMember6();
|
||||
benchmark.ArrayInstanceMemberLocalVar5();
|
||||
benchmark.ArrayInstanceMemberLocalVar6();
|
||||
benchmark.IntInstanceMember2();
|
||||
benchmark.IntInstanceMember3();
|
||||
benchmark.IntInstanceMember4();
|
||||
benchmark.IntInstanceMember5();
|
||||
benchmark.RefToArray2();
|
||||
benchmark.RefToArray3();
|
||||
benchmark.RefToArray4();
|
||||
benchmark.RefToArray5();
|
||||
benchmark.RefToArray6();
|
||||
benchmark.RefToInt2();
|
||||
benchmark.RefToInt3();
|
||||
}
|
||||
|
||||
private readonly TestCase _testCase = new();
|
||||
private static void DoNothing(int count)
|
||||
{
|
||||
_ = count;
|
||||
}
|
||||
|
||||
private class TestCase
|
||||
{
|
||||
private int[] _items = new int[123];
|
||||
private int _count = 123;
|
||||
private static int Add(int count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get => _count;
|
||||
set => _count = value;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount2()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount3()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
_ = TestCase.Add(count);
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount4()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
_ = TestCase.Add(count);
|
||||
_ = TestCase.Add(count);
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public ref int GetCountAsRefCount5()
|
||||
{
|
||||
ref int count = ref _count;
|
||||
count = 234;
|
||||
_ = TestCase.Add(count);
|
||||
_ = TestCase.Add(count);
|
||||
_ = TestCase.Add(count);
|
||||
return ref count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember2()
|
||||
{
|
||||
_count = 234;
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember3()
|
||||
{
|
||||
_count = 234;
|
||||
_ = TestCase.Add(_count);
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember4()
|
||||
{
|
||||
_count = 234;
|
||||
_ = TestCase.Add(_count);
|
||||
_ = TestCase.Add(_count);
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetCountAsInstanceMember5()
|
||||
{
|
||||
_count = 234;
|
||||
_ = TestCase.Add(_count);
|
||||
_ = TestCase.Add(_count);
|
||||
_ = TestCase.Add(_count);
|
||||
return _count;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray2()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray3()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray4()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray5()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArray6()
|
||||
{
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
_ = TestCase.Add(_items.Length);
|
||||
return _items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArrayLocalVar5()
|
||||
{
|
||||
var items = _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsArrayLocalVar6()
|
||||
{
|
||||
var items = _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray2()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray3()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray4()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray5()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
|
||||
public int GetLengthAsRefArray6()
|
||||
{
|
||||
ref int[] items = ref _items;
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
_ = TestCase.Add(items.Length);
|
||||
return items.Length;
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt2()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount2();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt3()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount3();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt4()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount4();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToInt5()
|
||||
{
|
||||
var count = _testCase.GetCountAsRefCount5();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void IntInstanceMember2()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember2();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void IntInstanceMember3()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember3();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void IntInstanceMember4()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember4();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void IntInstanceMember5()
|
||||
{
|
||||
var count = _testCase.GetCountAsInstanceMember5();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray2()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray2();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray3()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray3();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray4()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray4();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray5()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray5();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RefToArray6()
|
||||
{
|
||||
var count = _testCase.GetLengthAsRefArray6();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember2()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray2();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember3()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray3();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember4()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray4();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember5()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray5();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMember6()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArray6();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMemberLocalVar5()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArrayLocalVar5();
|
||||
DoNothing(count);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = false)]
|
||||
public void ArrayInstanceMemberLocalVar6()
|
||||
{
|
||||
var count = _testCase.GetLengthAsArrayLocalVar6();
|
||||
DoNothing(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
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 BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(RoundBenchmarkType.MathRound, RoundBenchmarkType.WithTypecasting)]
|
||||
public override RoundBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
private const double OptimalParallelSearchStep = 0.329;
|
||||
|
||||
public void RoundWithMathFloor()
|
||||
{
|
||||
DoNothing((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),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
static class RoundUpToPowerOf2Alternatives
|
||||
{
|
||||
private static readonly int[] PowersOfTwo =
|
||||
{
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
|
||||
2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576,
|
||||
2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824
|
||||
};
|
||||
|
||||
public static int BinarySearch(int value)
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw new ArgumentException("Input must be a positive integer.");
|
||||
}
|
||||
|
||||
// Find the smallest power of 2 greater than or equal to value using a lookup table
|
||||
int index = Array.BinarySearch(PowersOfTwo, value);
|
||||
if (index < 0)
|
||||
{
|
||||
// If value is not a power of 2, use the next power of 2 from the table
|
||||
index = ~index;
|
||||
}
|
||||
|
||||
return PowersOfTwo[index];
|
||||
}
|
||||
|
||||
public static int RightBitShifting(int value)
|
||||
{
|
||||
// Decrease value by 1 to handle the case where the input is already a power of 2
|
||||
value--;
|
||||
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
|
||||
return value + 1;
|
||||
}
|
||||
|
||||
public static int LeftBitShifting(int value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ensure value is a power of 2 or the next power of 2
|
||||
int result = 1;
|
||||
while (result < value)
|
||||
{
|
||||
result = checked(result << 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public enum RoundUpToPowerOf2BenchmarkType
|
||||
{
|
||||
Undefined,
|
||||
BitOperations,
|
||||
RightBitShifting,
|
||||
LeftBitShifting,
|
||||
BinarySearch,
|
||||
IsPowOf2,
|
||||
IsPowOf2_GreaterThanFirst,
|
||||
IsPowOf2_WithIf,
|
||||
IsPowOf2_GreaterEqual,
|
||||
}
|
||||
|
||||
public class RoundUpToPowerOf2vsOtherBenchmarks : PocBenchmarkBase<RoundUpToPowerOf2BenchmarkType>
|
||||
{
|
||||
// [Params(-850_000, 850_000)]
|
||||
[Params(-int.MaxValue, int.MaxValue)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
[Params(RoundUpToPowerOf2BenchmarkType.IsPowOf2)]
|
||||
public override RoundUpToPowerOf2BenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterThanFirst, RoundUpToPowerOf2BenchmarkType.IsPowOf2_WithIf, RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterEqual)]
|
||||
// [Params(RoundUpToPowerOf2BenchmarkType.RightBitShifting, RoundUpToPowerOf2BenchmarkType.LeftBitShifting, RoundUpToPowerOf2BenchmarkType.BinarySearch)]
|
||||
public override RoundUpToPowerOf2BenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
private void BitOperations()
|
||||
{
|
||||
DoNothing(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount));
|
||||
}
|
||||
|
||||
private void RightBitShifting()
|
||||
{
|
||||
DoNothing(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount));
|
||||
}
|
||||
|
||||
private void LeftBitShifting()
|
||||
{
|
||||
DoNothing(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount));
|
||||
}
|
||||
|
||||
private void BinarySearch()
|
||||
{
|
||||
DoNothing(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount));
|
||||
}
|
||||
|
||||
private void IsPowOf2()
|
||||
{
|
||||
DoNothing((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0);
|
||||
}
|
||||
|
||||
private void IsPowOf2_GreaterThanFirst()
|
||||
{
|
||||
DoNothing(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
|
||||
}
|
||||
|
||||
private void IsPowOf2_WithIf()
|
||||
{
|
||||
DoNothing(TestObjectCount > 0 ? (TestObjectCount & (TestObjectCount - 1)) == 0 : false);
|
||||
}
|
||||
|
||||
private void IsPowOf2_GreaterEqual()
|
||||
{
|
||||
DoNothing(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(RoundUpToPowerOf2BenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
RoundUpToPowerOf2BenchmarkType.BitOperations => BitOperations,
|
||||
RoundUpToPowerOf2BenchmarkType.RightBitShifting => RightBitShifting,
|
||||
RoundUpToPowerOf2BenchmarkType.LeftBitShifting => LeftBitShifting,
|
||||
RoundUpToPowerOf2BenchmarkType.BinarySearch => BinarySearch,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2 => IsPowOf2,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterThanFirst => IsPowOf2_GreaterThanFirst,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2_WithIf => IsPowOf2_WithIf,
|
||||
RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterEqual => IsPowOf2_GreaterEqual,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
protected override void PrepareData<T>(T benchmarkType)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum SpanConstructorVsTypecastingPocBenchmarkType
|
||||
{
|
||||
Unknown,
|
||||
Constructor,
|
||||
TypeCasting,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class SpanConstructorVsTypecastingPocBenchmarks : PocBenchmarkBase<SpanConstructorVsTypecastingPocBenchmarkType>
|
||||
{
|
||||
private int[]? TestData { get; set; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
|
||||
private void DoNothing(ReadOnlySpan<int> span) { }
|
||||
|
||||
[Params(SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting)]
|
||||
public override SpanConstructorVsTypecastingPocBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(SpanConstructorVsTypecastingPocBenchmarkType.Constructor)]
|
||||
public override SpanConstructorVsTypecastingPocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(8)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new SpanConstructorVsTypecastingPocBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Constructor();
|
||||
benchmark.TypeCasting();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
public void Constructor()
|
||||
{
|
||||
ReadOnlySpan<int> span = new(TestData);
|
||||
DoNothing(span);
|
||||
}
|
||||
|
||||
public void TypeCasting()
|
||||
{
|
||||
ReadOnlySpan<int> span = TestData;
|
||||
DoNothing(span);
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
TestData = new int[TestObjectCount];
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(SpanConstructorVsTypecastingPocBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
SpanConstructorVsTypecastingPocBenchmarkType.Constructor => Constructor,
|
||||
SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting => TypeCasting,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
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 DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(SpanVsArrayBenchmarkType.ArrayGetWithField)]
|
||||
// [Params(SpanVsArrayBenchmarkType.ArraySetWithField)]
|
||||
public override SpanVsArrayBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
protected override Action GetTestMethod(SpanVsArrayBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithVar => ArrayGetWithVar,
|
||||
SpanVsArrayBenchmarkType.ArrayGetWithField => ArrayGetWithField,
|
||||
SpanVsArrayBenchmarkType.SpanGet => SpanGet,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithVar => ArraySetWithVar,
|
||||
SpanVsArrayBenchmarkType.ArraySetWithField => ArraySetWithField,
|
||||
SpanVsArrayBenchmarkType.SpanSet => SpanSet,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
|
||||
public void ArrayGetWithVar()
|
||||
{
|
||||
var data = TestObjects;
|
||||
var dataCount = TestObjectCount;
|
||||
for (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
@@ -1,63 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Recyclable.Collections.Benchmarks.POC;
|
||||
|
||||
#pragma warning disable RCS1036, RCS1213, IDE0051
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
static IConfig BenchmarkConfig { get; } = ManualConfig.Create(DefaultConfig.Instance)
|
||||
.WithOptions(ConfigOptions.DisableOptimizationsValidator | ConfigOptions.JoinSummary);
|
||||
|
||||
static void RunAssemblyBenchmarks()
|
||||
{
|
||||
_ = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(new[] { "-f*" });
|
||||
}
|
||||
|
||||
private static void RunRecyclableCollectionsBenchmarks()
|
||||
{
|
||||
_ = BenchmarkRunner.Run<RecyclableCollectionsBenchmarks>(BenchmarkConfig);
|
||||
}
|
||||
|
||||
static void RunSelectedBenchmarks()
|
||||
{
|
||||
// ****************
|
||||
// *** Template ***
|
||||
// ****************
|
||||
var benchmark = new RecyclableCollectionsBenchmarks();
|
||||
benchmark.Setup();
|
||||
|
||||
foreach (var _ in Enumerable.Range(1, 1000))
|
||||
{
|
||||
// benchmark.RecyclableList_Create_WithCapacity();
|
||||
}
|
||||
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
static void RunPocBenchmarks()
|
||||
{
|
||||
_ = BenchmarkRunner.Run<BoolOrComparePocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<DelegateVsComparerPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<ModuloPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RefVsInstanceMemberPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<SpanVsArrayBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<LessOperatorVsAndOperatorBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<EqualVsContainsInConsecutiveOrderBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundUpToPowerOf2vsOtherBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<GreaterOperatorVsDoesntEqualOperatorBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<SpanConstructorVsTypecastingPocBenchmarks>(BenchmarkConfig);
|
||||
// ArraySizeLimitPocBenchmarks>(BenchmarkConfig);
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
RunRecyclableCollectionsBenchmarks();
|
||||
// RunPocBenchmarks();
|
||||
// RunSelectedBenchmarks();
|
||||
// RunAssemblyBenchmarks();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"WSL": {
|
||||
"commandName": "WSL2",
|
||||
"distributionName": ""
|
||||
},
|
||||
".Net": {
|
||||
"commandName": "Project",
|
||||
"nativeDebugging": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<StartupObject>Recyclable.Collections.Benchmarks.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
|
||||
<PackageReference Include="Collections.Pooled" Version="1.0.82" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Recyclable.CollectionsTests\Recyclable.CollectionsTests.csproj" />
|
||||
<ProjectReference Include="..\Recyclable.Collections\Recyclable.Collections.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,340 +0,0 @@
|
||||
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 wrong 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, initialCapacity: base.TestObjectCount);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw CreateUnknownBenchmarkTypeException(benchmarkType);
|
||||
}
|
||||
|
||||
base.PrepareData(benchmarkType);
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
Console.WriteLine("******* GLOBAL CLEANUP *******");
|
||||
// Enable this if item type is changed to reference type
|
||||
//if (_testObjects != null)
|
||||
//{
|
||||
// Array.Fill(_testObjects, 0);
|
||||
//}
|
||||
|
||||
_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();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Recyclable.Collections", "R
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Recyclable.CollectionsTests", "Recyclable.CollectionsTests\Recyclable.CollectionsTests.csproj", "{2B7223FA-2D5B-40BF-9BD9-9D6B05DC18E2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Recyclable.Collections.Benchmarks", "Recyclable.Collections.Benchmarks\Recyclable.Collections.Benchmarks.csproj", "{CDC0CF78-FC11-43E3-9059-3261DA3639D1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -33,14 +31,6 @@ Global
|
||||
{2B7223FA-2D5B-40BF-9BD9-9D6B05DC18E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2B7223FA-2D5B-40BF-9BD9-9D6B05DC18E2}.Release|x64.ActiveCfg = Release|x64
|
||||
{2B7223FA-2D5B-40BF-9BD9-9D6B05DC18E2}.Release|x64.Build.0 = Release|x64
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Debug|x64.Build.0 = Debug|x64
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Release|x64.ActiveCfg = Release|x64
|
||||
{CDC0CF78-FC11-43E3-9059-3261DA3639D1}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
return CompareResult.XEqualY;
|
||||
}
|
||||
#pragma warning disable IDE0046 // This is intentional due to better performance - IL contained unnecessary local variable.
|
||||
else if (x != null && y == null)
|
||||
{
|
||||
return CompareResult.XGreaterThenY;
|
||||
@@ -27,6 +28,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
return _comparison(x!, y!);
|
||||
}
|
||||
#pragma warning restore IDE0046
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
internal static class ExceptionExtensions
|
||||
{
|
||||
public static void CaptureAndRethrow(this Exception ex)
|
||||
public static void CaptureAndReThrow(this Exception ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex).Throw();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
// Ignore Spelling: Linq
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// The source code was taken from
|
||||
// https://codereview.stackexchange.com/questions/205407/quicksort-without-recursion.
|
||||
|
||||
@@ -31,5 +31,14 @@ namespace Recyclable.Collections
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static long Min(long number1, long number2, long number3) =>
|
||||
number1 <= number2
|
||||
? number1 <= number3
|
||||
? number1
|
||||
: number3
|
||||
: number2 <= number3
|
||||
? number2
|
||||
: number3;
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,12 @@ namespace Recyclable.Collections
|
||||
_memory = memory;
|
||||
}
|
||||
|
||||
#pragma warning disable RCS1085
|
||||
#pragma warning disable IDE0032 // This is intentional due to better performance
|
||||
private T[] _memory;
|
||||
public T[] Memory { get => _memory; set => _memory = value; }
|
||||
|
||||
private MemoryBucket<T>? _nextBucket;
|
||||
#pragma warning restore IDE0032 // Use auto property
|
||||
public MemoryBucket<T>? NextBucket { get => _nextBucket; set => _nextBucket = value; }
|
||||
#pragma warning restore RCS1085
|
||||
}
|
||||
}
|
||||
@@ -7,26 +7,20 @@ namespace Recyclable.Collections.Pools
|
||||
Low
|
||||
}
|
||||
|
||||
internal static class MemoryUtils
|
||||
{
|
||||
public static MemoryPressure GetMemoryPressure()
|
||||
{
|
||||
const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high"
|
||||
const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium"
|
||||
internal static class MemoryUtils
|
||||
{
|
||||
private const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high"
|
||||
private const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium"
|
||||
|
||||
GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo();
|
||||
public static MemoryPressure GetMemoryPressure()
|
||||
{
|
||||
GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo();
|
||||
|
||||
if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * HighPressureThreshold)
|
||||
{
|
||||
return MemoryPressure.High;
|
||||
}
|
||||
|
||||
if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * MediumPressureThreshold)
|
||||
{
|
||||
return MemoryPressure.Medium;
|
||||
}
|
||||
|
||||
return MemoryPressure.Low;
|
||||
}
|
||||
}
|
||||
return memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * HighPressureThreshold
|
||||
? MemoryPressure.High
|
||||
: memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * MediumPressureThreshold
|
||||
? MemoryPressure.Medium
|
||||
: MemoryPressure.Low;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Recyclable.Collections</PackageId>
|
||||
<PackageVersion>0.0.6</PackageVersion>
|
||||
<PackageVersion>0.0.6.2</PackageVersion>
|
||||
<Authors>Marek Lemańczyk</Authors>
|
||||
<Company>N/A</Company>
|
||||
<Product>Recyclable.Collections</Product>
|
||||
@@ -17,11 +17,15 @@
|
||||
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageReleaseNotes>List<T> compatibility pack added for RecyclableList<T>. Various performance improvements and fixes.</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>Various bug fixes and improvements, primarily for .IndexOf().</PackageReleaseNotes>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<PackageIcon>logo.png</PackageIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\logo.png" Pack="true" PackagePath="" Link="logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\LICENSE.md" Pack="true" PackagePath="" Link="LICENSE.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
@@ -31,7 +35,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.5" />
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -4,7 +4,9 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
#pragma warning disable IDE1006 // This is intentional naming for the class to show up at the end of IntelliSense list.
|
||||
public static class zRecyclableListAddRange
|
||||
#pragma warning restore IDE1006 // This is intentional naming for the class to show up at the end of IntelliSense list.
|
||||
{
|
||||
private static void AddRangeEnumerated<T>(this RecyclableList<T> list, IEnumerable<T> items, int growByCount)
|
||||
{
|
||||
|
||||
@@ -1,272 +0,0 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityListFind
|
||||
{
|
||||
public static bool Exists<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static T? Find<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return sourceSpan[itemIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public static RecyclableList<T> FindAll<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<T> result = new(sourceItemsCount >> 3);
|
||||
Span<T> resultSpan = result._memoryBlock;
|
||||
int capacity = result._capacity,
|
||||
resultItemsCount = 0;
|
||||
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
if (resultItemsCount + 1 > capacity)
|
||||
{
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1));
|
||||
_ = RecyclableListHelpers<T>.EnsureCapacity(result, resultItemsCount, capacity);
|
||||
resultSpan = result._memoryBlock;
|
||||
}
|
||||
|
||||
resultSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
||||
}
|
||||
}
|
||||
|
||||
result._capacity = capacity;
|
||||
result._count = resultItemsCount;
|
||||
return result;
|
||||
}
|
||||
public static RecyclableList<int> FindAllIndexes<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<int> result = new(sourceItemsCount >> 3);
|
||||
Span<int> resultSpan = result._memoryBlock;
|
||||
int capacity = result._capacity,
|
||||
resultItemsCount = 0;
|
||||
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
if (resultItemsCount + 1 > capacity)
|
||||
{
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1));
|
||||
_ = RecyclableListHelpers<int>.EnsureCapacity(result, resultItemsCount, capacity);
|
||||
resultSpan = result._memoryBlock;
|
||||
}
|
||||
|
||||
resultSpan[resultItemsCount++] = itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
result._capacity = capacity;
|
||||
result._count = resultItemsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int FindIndex<T>(this RecyclableList<T> list, int startIndex, int count, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0 || startIndex >= sourceItemsCount)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindIndex<T>(this RecyclableList<T> list, int startIndex, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0 || startIndex >= sourceItemsCount)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindIndex<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static T? FindLast<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
if (list._count == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return sourceSpan[itemIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public static int FindLastIndex<T>(this RecyclableList<T> list, int startIndex, int count, Predicate<T> match)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
if (startIndex != -1)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||
}
|
||||
}
|
||||
else if (count < 0 || startIndex - count + 1 < 0)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Count();
|
||||
}
|
||||
|
||||
if (startIndex < 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int sourceItemsCount = count; // startIndex - count + 1 >= 0 ? count : startIndex + 1;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int lastItemIndex = startIndex - sourceItemsCount;
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex > lastItemIndex; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindLastIndex<T>(this RecyclableList<T> list, int startIndex, Predicate<T> match)
|
||||
{
|
||||
if (list._count == 0 || startIndex < 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
public static int FindLastIndex<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
if (list._count == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityListIndexOf
|
||||
{
|
||||
public static int IndexOf<T>(this RecyclableList<T> list, T item, int index) => list._count != 0
|
||||
? Array.IndexOf(list._memoryBlock, item, index, list._count - index)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int IndexOf<T>(this RecyclableList<T> list, T item, int index, int count) => list._count != 0
|
||||
? Array.IndexOf(list._memoryBlock, item, index, count)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int LastIndexOf<T>(this RecyclableList<T> list, T item) => list._count != 0
|
||||
? Array.LastIndexOf(list._memoryBlock, item, list._count - 1)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int LastIndexOf<T>(this RecyclableList<T> list, T item, int index) => list._count != 0
|
||||
? Array.LastIndexOf(list._memoryBlock, item, index)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
public static int LastIndexOf<T>(this RecyclableList<T> list, T item, int index, int count) => list._count != 0
|
||||
? Array.LastIndexOf(list._memoryBlock, item, index, count)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityListInsertRange
|
||||
{
|
||||
private static void InsertRangeEnumerated<T>(this RecyclableList<T> list, int index, IEnumerable<T> items, int growByCount)
|
||||
{
|
||||
var enumerator = items.GetEnumerator();
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int capacity = list._capacity,
|
||||
added = 0,
|
||||
available = capacity - list._count,
|
||||
i,
|
||||
movingBlockLength = list._count - index;
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
if (available > 0)
|
||||
{
|
||||
Array.Copy(memoryBlock, index, memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
|
||||
Span<T> memorySpan = memoryBlock;
|
||||
do
|
||||
{
|
||||
if (index + available + movingBlockLength > capacity)
|
||||
{
|
||||
var capacityBeforeIncrease = capacity;
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)(capacity + growByCount)));
|
||||
_ = RecyclableListHelpers<T>.EnsureCapacity(list, memoryBlock.Length, capacity);
|
||||
memorySpan = memoryBlock = list._memoryBlock;
|
||||
available = capacity - index - movingBlockLength;
|
||||
Array.Copy(memoryBlock, capacityBeforeIncrease - movingBlockLength, memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
|
||||
for (i = 0; i < available; i++)
|
||||
{
|
||||
memorySpan[index++] = enumerator.Current;
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
added++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
added += i;
|
||||
}
|
||||
while (i == available);
|
||||
|
||||
if (i != available)
|
||||
{
|
||||
Array.Copy(memoryBlock, capacity - movingBlockLength, memoryBlock, index, movingBlockLength);
|
||||
if (RecyclableList<T>._needsClearing)
|
||||
{
|
||||
Array.Clear(memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
}
|
||||
|
||||
list._count += added;
|
||||
list._capacity = capacity;
|
||||
}
|
||||
|
||||
private static void InsertRangeWithKnownCount<T>(this RecyclableList<T> list, int index, IEnumerable<T> items, int currentItemsCount, int requiredAdditionalCapacity)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity))));
|
||||
|
||||
Array.Copy(list._memoryBlock, index, list._memoryBlock, index + requiredAdditionalCapacity, list._count - index);
|
||||
Span<T> memorySpan = list._memoryBlock;
|
||||
foreach (var item in items)
|
||||
{
|
||||
memorySpan[index++] = item;
|
||||
}
|
||||
|
||||
list._count += requiredAdditionalCapacity;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, in Array items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
Array.Copy(items, items.GetLowerBound(0), memoryBlock, index, items.Length);
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, in T[] items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
new ReadOnlySpan<T>(items).CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, ReadOnlySpan<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
items.CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, Span<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
items.CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, List<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, ICollection items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(list._memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, ICollection<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, RecyclableList<T> items)
|
||||
{
|
||||
if (list._capacity < list._count + items._count)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items._count))));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
new ReadOnlySpan<T>(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count));
|
||||
list._count += items._count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, RecyclableLongList<T> items)
|
||||
{
|
||||
if (items._longCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int oldCount = list._count;
|
||||
long sourceItemsCount = items._longCount;
|
||||
if (oldCount + sourceItemsCount > int.MaxValue)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), $"The total number of items in source and target table exceeds the maximum capacity of {nameof(RecyclableList<T>)}, equal {int.MaxValue}. Please consider using {nameof(RecyclableLongList<T>)}, instead");
|
||||
}
|
||||
|
||||
int targetCapacity = oldCount + (int)sourceItemsCount;
|
||||
if (list._capacity < targetCapacity)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||
}
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, oldCount - index);
|
||||
Span<T> targetSpan = new(list._memoryBlock, index, list._capacity - index),
|
||||
itemsSpan;
|
||||
|
||||
int blockIndex,
|
||||
sourceBlockSize = items._blockSize,
|
||||
lastBlockIndex = (int)(sourceItemsCount >> items._blockSizePow2BitShift) - 1;
|
||||
|
||||
for (blockIndex = 0; blockIndex <= lastBlockIndex; blockIndex++)
|
||||
{
|
||||
itemsSpan = new(items._memoryBlocks[blockIndex], 0, sourceBlockSize);
|
||||
itemsSpan.CopyTo(targetSpan);
|
||||
targetSpan = targetSpan[sourceBlockSize..];
|
||||
}
|
||||
|
||||
if (blockIndex == 0)
|
||||
{
|
||||
itemsSpan = new(items._memoryBlocks[blockIndex], 0, (int)sourceItemsCount);
|
||||
itemsSpan.CopyTo(targetSpan);
|
||||
}
|
||||
else if (blockIndex <= items._lastBlockWithData)
|
||||
{
|
||||
itemsSpan = new(items._memoryBlocks[blockIndex], 0, items._nextItemIndex > 0 ? items._nextItemIndex : sourceBlockSize);
|
||||
itemsSpan.CopyTo(targetSpan);
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static IEnumerator InsertRange<T>(this RecyclableList<T> list, int index, IEnumerable source, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
int targetItemIndex = list._count;
|
||||
Span<T> memorySpan;
|
||||
|
||||
int i;
|
||||
var enumerator = source.GetEnumerator();
|
||||
|
||||
int capacity = list._capacity;
|
||||
memorySpan = list._memoryBlock;
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
int available = capacity - targetItemIndex;
|
||||
do
|
||||
{
|
||||
if (targetItemIndex + growByCount > capacity)
|
||||
{
|
||||
capacity = RecyclableListHelpers<T>.EnsureCapacity(list, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount))));
|
||||
memorySpan = list._memoryBlock;
|
||||
available = capacity - targetItemIndex;
|
||||
}
|
||||
|
||||
for (i = 0; i < available; i++)
|
||||
{
|
||||
memorySpan[targetItemIndex++] = (T)enumerator.Current;
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i >= available);
|
||||
}
|
||||
|
||||
list._capacity = capacity;
|
||||
list._count = targetItemIndex;
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, IReadOnlyList<T> items)
|
||||
{
|
||||
int sourceItemsCount = items.Count;
|
||||
if (list._capacity < list._count + sourceItemsCount)
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + sourceItemsCount))));
|
||||
}
|
||||
|
||||
Span<T> memorySpan = new(list._memoryBlock, list._count, sourceItemsCount);
|
||||
for (var sourceItemIndex = 0; sourceItemIndex < sourceItemsCount; sourceItemIndex++)
|
||||
{
|
||||
memorySpan[sourceItemIndex] = items[sourceItemIndex];
|
||||
}
|
||||
|
||||
list._count += sourceItemsCount;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void InsertRange<T>(this RecyclableList<T> list, int index, IEnumerable<T> items, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
if (items is RecyclableList<T> sourceRecyclableList)
|
||||
{
|
||||
InsertRange(list, index, sourceRecyclableList);
|
||||
}
|
||||
else if (items is RecyclableLongList<T> sourceRecyclableLongList)
|
||||
{
|
||||
InsertRange(list, index, sourceRecyclableLongList);
|
||||
}
|
||||
else if (items is T[] sourceArray)
|
||||
{
|
||||
InsertRange(list, index, sourceArray);
|
||||
}
|
||||
else if (items is Array sourceArrayWithObjects)
|
||||
{
|
||||
InsertRange(list, index, sourceArrayWithObjects);
|
||||
}
|
||||
else if (items is List<T> sourceList)
|
||||
{
|
||||
InsertRange(list, index, sourceList);
|
||||
}
|
||||
else if (items is ICollection<T> sourceICollection)
|
||||
{
|
||||
InsertRange(list, index, sourceICollection);
|
||||
}
|
||||
else if (items is ICollection sourceICollectionWithObjects)
|
||||
{
|
||||
InsertRange(list, index, sourceICollectionWithObjects);
|
||||
}
|
||||
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
||||
{
|
||||
InsertRange(list, index, sourceIReadOnlyList);
|
||||
}
|
||||
else if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity) && requiredAdditionalCapacity != 0)
|
||||
{
|
||||
InsertRangeWithKnownCount(list, index, items, list._count, requiredAdditionalCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertRangeEnumerated(list, index, items, growByCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Numerics;
|
||||
using Recyclable.Collections.Pools;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
|
||||
[Obsolete("It'll be moved to Recyclable.Collections.Compatibility.List NuGet package in the next release.")]
|
||||
public static class zRecyclableListCompatibilityList
|
||||
{
|
||||
public static ReadOnlyCollection<T> AsReadOnly<T>(this RecyclableList<T> list) => new(list);
|
||||
|
||||
public static int BinarySearch<T>(this RecyclableList<T> list, T item)
|
||||
=> Array.BinarySearch(list._memoryBlock, 0, list._count, item);
|
||||
|
||||
public static int BinarySearch<T>(this RecyclableList<T> list, T item, IComparer<T>? comparer)
|
||||
=> Array.BinarySearch(list._memoryBlock, 0, list._count, item, comparer);
|
||||
|
||||
public static int BinarySearch<T>(this RecyclableList<T> list, int index, int count, T item, IComparer<T>? comparer)
|
||||
=> Array.BinarySearch(list._memoryBlock, index, count, item, comparer);
|
||||
|
||||
public static RecyclableList<TOutput> ConvertAll<T, TOutput>(this RecyclableList<T> list, Converter<T, TOutput> converter)
|
||||
{
|
||||
int itemsCount = list._count;
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
RecyclableList<TOutput> result = new(itemsCount);
|
||||
TOutput[] resultSpan = result._memoryBlock;
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (int bufferIndex = 0; bufferIndex < itemsCount; bufferIndex++)
|
||||
{
|
||||
resultSpan[bufferIndex] = converter(sourceSpan[bufferIndex]);
|
||||
}
|
||||
|
||||
result._count = itemsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void CopyTo<T>(this RecyclableList<T> list, T[] array) => Array.Copy(list._memoryBlock, array, list._count);
|
||||
|
||||
public static void CopyTo<T>(this RecyclableList<T> list, int index, T[] array, int arrayIndex, int count) => Array.Copy(list._memoryBlock, index, array, arrayIndex, count);
|
||||
|
||||
public static void ForEach<T>(this RecyclableList<T> list, Action<T> action)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
action(sourceSpan[itemIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
public static RecyclableList<T> GetRange<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
int sourceItemsCount = index + count <= list._count ? count : list._count - index;
|
||||
if (sourceItemsCount <= 0)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<T> result = new(sourceItemsCount);
|
||||
Span<T> targetSpan = result._memoryBlock;
|
||||
int resultItemsCount = 0;
|
||||
sourceItemsCount += index;
|
||||
for (var itemIndex = index; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
targetSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
||||
}
|
||||
|
||||
result._count = resultItemsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int RemoveAll<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
using var allIndexes = list.FindAllIndexes(match);
|
||||
int foundItemsCount = allIndexes._count;
|
||||
if (foundItemsCount == 0)
|
||||
{
|
||||
return foundItemsCount;
|
||||
}
|
||||
|
||||
for (int removed = 0; removed < foundItemsCount; removed++)
|
||||
{
|
||||
var indexToRemove = allIndexes[removed] - removed;
|
||||
Array.Copy(list._memoryBlock, indexToRemove + 1, list._memoryBlock, indexToRemove, list._count - indexToRemove - removed - 1);
|
||||
}
|
||||
|
||||
if (RecyclableList<T>._needsClearing)
|
||||
{
|
||||
Array.Clear(list._memoryBlock, list._count - foundItemsCount, foundItemsCount);
|
||||
}
|
||||
|
||||
list._count -= foundItemsCount;
|
||||
list._version++;
|
||||
return foundItemsCount;
|
||||
}
|
||||
|
||||
public static void RemoveRange<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
int oldCount = list._count;
|
||||
count = count - index + 1 <= oldCount ? count : oldCount - index + 1;
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (index + count < oldCount)
|
||||
{
|
||||
Array.Copy(list._memoryBlock, index + count, list._memoryBlock, index, oldCount - count - index);
|
||||
}
|
||||
|
||||
if (RecyclableList<T>._needsClearing)
|
||||
{
|
||||
Array.Clear(list._memoryBlock, oldCount - count, count);
|
||||
}
|
||||
|
||||
list._count -= count;
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Reverse<T>(this RecyclableList<T> list)
|
||||
{
|
||||
Array.Reverse(list._memoryBlock, 0, list._count);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Reverse<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
Array.Reverse(list._memoryBlock, index, count);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, Comparison<T> comparison)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count, new ComparisonToComparerAdapter<T>(comparison));
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, IComparer<T>? comparer)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count, comparer);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, int index, int count, IComparer<T>? comparer)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, index, count, comparer);
|
||||
list._version++;
|
||||
}
|
||||
|
||||
public static T[] ToArray<T>(this RecyclableList<T> list)
|
||||
{
|
||||
T[] result = new T[list._count];
|
||||
new ReadOnlySpan<T>(list._memoryBlock, 0, list._count).CopyTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void TrimExcess<T>(this RecyclableList<T> list)
|
||||
{
|
||||
var requiredCapacity = list._count >= RecyclableDefaults.InitialCapacity ? list._count : RecyclableDefaults.InitialCapacity;
|
||||
|
||||
T[] oldMemoryBlock = list._memoryBlock;
|
||||
T[] result = requiredCapacity >= RecyclableDefaults.MinPooledArrayLength && BitOperations.IsPow2(requiredCapacity)
|
||||
? RecyclableArrayPool<T>.RentShared(requiredCapacity)
|
||||
: new T[requiredCapacity];
|
||||
|
||||
new ReadOnlySpan<T>(oldMemoryBlock, 0, list._count).CopyTo(result);
|
||||
|
||||
if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, RecyclableList<T>._needsClearing);
|
||||
}
|
||||
|
||||
list._memoryBlock = result;
|
||||
list._capacity = requiredCapacity;
|
||||
}
|
||||
|
||||
public static bool TrueForAll<T>(this RecyclableList<T> list, Predicate<T> match)
|
||||
{
|
||||
int sourceItemsCount = list._count;
|
||||
if (sourceItemsCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (!match(sourceSpan[itemIndex]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
internal static class RecyclableListHelpers<T>
|
||||
{
|
||||
private static readonly bool NeedsClearing = !typeof(T).IsValueType;
|
||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||
|
||||
public static int CalculateIndex(int index, int lowerBound) => index >= 0 ? index + lowerBound : RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Recyclable.Collections
|
||||
// Array.Clear(source);
|
||||
//}
|
||||
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, NeedsClearing);
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, _needsClearing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Recyclable.Collections
|
||||
//}
|
||||
|
||||
// If anything, it has been already cleared above, so we don't need to repeat it.
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, NeedsClearing);
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, _needsClearing);
|
||||
}
|
||||
|
||||
return newSize;
|
||||
@@ -80,7 +80,7 @@ namespace Recyclable.Collections
|
||||
//}
|
||||
|
||||
// If anything, it has been already cleared above, so we don't need to repeat it.
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, NeedsClearing);
|
||||
RecyclableArrayPool<T>.ReturnShared(oldMemoryBlock, _needsClearing);
|
||||
}
|
||||
|
||||
return newSize;
|
||||
|
||||
@@ -41,22 +41,6 @@ namespace Recyclable.Collections
|
||||
}
|
||||
}
|
||||
|
||||
public RecyclableList(int initialCapacity, int lowerBound)
|
||||
{
|
||||
if (initialCapacity >= RecyclableDefaults.InitialCapacity)
|
||||
{
|
||||
_memoryBlock = initialCapacity >= RecyclableDefaults.MinPooledArrayLength
|
||||
? RecyclableArrayPool<T>.RentShared(checked((int)BitOperations.RoundUpToPowerOf2((uint)initialCapacity)))
|
||||
: new T[initialCapacity];
|
||||
_capacity = _memoryBlock.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
_memoryBlock = new T[RecyclableDefaults.InitialCapacity];
|
||||
_capacity = RecyclableDefaults.InitialCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
public RecyclableList(in Array source)
|
||||
{
|
||||
_capacity = RecyclableDefaults.InitialCapacity;
|
||||
@@ -260,6 +244,16 @@ namespace Recyclable.Collections
|
||||
? Array.IndexOf(_memoryBlock, itemToFind, 0, _count)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IndexOf(T item, int index) => _count != 0
|
||||
? Array.IndexOf(_memoryBlock, item, index, _count - index)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IndexOf(T item, int index, int count) => _count != 0
|
||||
? Array.IndexOf(_memoryBlock, item, index, count)
|
||||
: RecyclableDefaults.ItemNotFoundIndex;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,9 @@ using Recyclable.Collections.Pools;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
#pragma warning disable IDE1006 // This is intentional naming for the class to show up at the end of IntelliSense list.
|
||||
public static class zRecyclableLongListAddRange
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
private static void AddRangeEnumerated<T>(this RecyclableLongList<T> targetList, IEnumerable<T> items)
|
||||
{
|
||||
@@ -30,7 +32,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
if (copied + blockSize > capacity)
|
||||
{
|
||||
capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(capacity + blockSize))));
|
||||
capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(capacity + blockSize))));
|
||||
memoryBlocksSpan = targetList._memoryBlocks;
|
||||
available = capacity - copied;
|
||||
}
|
||||
@@ -43,7 +45,7 @@ namespace Recyclable.Collections
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
targetList._lastBlockWithData = targetBlockIdx;
|
||||
targetList._longCount += copied + i - targetList._longCount;
|
||||
targetList._longCount = copied + i;
|
||||
if (targetItemIdx < blockSize)
|
||||
{
|
||||
targetList._nextItemBlockIndex = targetBlockIdx;
|
||||
@@ -91,7 +93,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (targetList._capacity < requiredCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
@@ -135,7 +137,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
@@ -184,7 +186,7 @@ namespace Recyclable.Collections
|
||||
long targetCapacity = targetList._longCount + items.Count;
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
// We're better off to temporarily copy it to a fixed array,
|
||||
@@ -250,7 +252,7 @@ namespace Recyclable.Collections
|
||||
long targetCapacity = targetList._longCount + items.Count;
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
// We're better off to temporarily copy it to a fixed array,
|
||||
@@ -330,7 +332,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
if (copied + blockSize > capacity)
|
||||
{
|
||||
capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(capacity + blockSize))));
|
||||
capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(capacity + blockSize))));
|
||||
memoryBlocksSpan = targetList._memoryBlocks;
|
||||
available = capacity - copied;
|
||||
}
|
||||
@@ -343,7 +345,7 @@ namespace Recyclable.Collections
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
targetList._lastBlockWithData = targetBlockIdx;
|
||||
targetList._longCount += copied + i - targetList._longCount;
|
||||
targetList._longCount = copied + i;
|
||||
if (targetItemIdx < blockSize)
|
||||
{
|
||||
targetList._nextItemBlockIndex = targetBlockIdx;
|
||||
@@ -443,7 +445,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (targetList._capacity < requiredCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
@@ -486,7 +488,7 @@ namespace Recyclable.Collections
|
||||
long targetCapacity = targetList._longCount + items.Count;
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
@@ -532,7 +534,7 @@ namespace Recyclable.Collections
|
||||
long targetCapacity = targetList._longCount + items.Length;
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
@@ -587,7 +589,7 @@ namespace Recyclable.Collections
|
||||
long targetCapacity = targetList._longCount + items._count;
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> itemsSpan = new(items._memoryBlock, 0, items._count);
|
||||
@@ -649,7 +651,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> sourceMemoryBlocksSpan = items._memoryBlocks;
|
||||
@@ -717,7 +719,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
@@ -772,7 +774,7 @@ namespace Recyclable.Collections
|
||||
long targetCapacity = targetList._longCount + items.LongLength;
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(ref targetList._memoryBlocks, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> itemsSpan = items;
|
||||
|
||||
@@ -16,7 +16,9 @@ namespace Recyclable.Collections
|
||||
private readonly RecyclableLongList<T> _list;
|
||||
|
||||
#nullable disable
|
||||
#pragma warning disable IDE0032 // This is intentional due to better performance
|
||||
private T _current;
|
||||
#pragma warning restore IDE0032
|
||||
#nullable restore
|
||||
|
||||
[Pure]
|
||||
|
||||
@@ -142,9 +142,9 @@ namespace Recyclable.Collections
|
||||
/// </remarks>
|
||||
/// <returns>The maximum no. of items <paramref name="list"/> can store.</returns>
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static long Resize(RecyclableLongList<T> list, int minBlockSize, byte minBlockSizePow2Shift, long newCapacity)
|
||||
public static long Resize(ref T[][] memoryBlocks, int minBlockSize, byte minBlockSizePow2Shift, long newCapacity)
|
||||
{
|
||||
int sourceBlockCount = list._memoryBlocks?.Length ?? 0;
|
||||
int sourceBlockCount = memoryBlocks?.Length ?? 0;
|
||||
int requiredBlockCount = checked((int)(newCapacity >> minBlockSizePow2Shift) + ((newCapacity & (minBlockSize - 1)) != 0 ? 1 : 0));
|
||||
int blockIndex;
|
||||
|
||||
@@ -157,19 +157,19 @@ namespace Recyclable.Collections
|
||||
// Copy arrays from the old memory block for all arrays
|
||||
if (sourceBlockCount > 0)
|
||||
{
|
||||
Array.Copy(list._memoryBlocks!, newMemoryBlocks, sourceBlockCount);
|
||||
Array.Copy(memoryBlocks!, newMemoryBlocks, sourceBlockCount);
|
||||
// We can now return the old memory block for all arrays itself
|
||||
if (sourceBlockCount >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
RecyclableArrayPool<T[]>.ReturnShared(list._memoryBlocks!, true);
|
||||
RecyclableArrayPool<T[]>.ReturnShared(memoryBlocks!, true);
|
||||
}
|
||||
}
|
||||
|
||||
list._memoryBlocks = newMemoryBlocks;
|
||||
memoryBlocks = newMemoryBlocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
newMemoryBlocks = list._memoryBlocks!;
|
||||
newMemoryBlocks = memoryBlocks!;
|
||||
}
|
||||
|
||||
// Allocate arrays for any new blocks
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace Recyclable.Collections
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static long IndexOfParallel(RecyclableLongList<T> list, T item)
|
||||
public static long IndexOfParallel(RecyclableLongList<T> list, T item)
|
||||
{
|
||||
// & WAS SLOWER
|
||||
//long itemsCount = Array.IndexOf(list._memoryBlocks[0], item, 0, (int)Math.Min(list._blockSize, list._longCount));
|
||||
@@ -284,7 +284,184 @@ namespace Recyclable.Collections
|
||||
|
||||
try
|
||||
{
|
||||
context.Exception.CaptureAndRethrow();
|
||||
context.Exception.CaptureAndReThrow();
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Dispose();
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static long IndexOfParallel(RecyclableLongList<T> list, T item, int firstBlockIndex)
|
||||
{
|
||||
IndexOfSynchronizationContext context = IndexOfSynchronizationContextPool.GetWithOneParticipant();
|
||||
|
||||
int blockIndex = firstBlockIndex,
|
||||
lastBlockWithData = list._lastBlockWithData,
|
||||
lastFullBlockWithData = lastBlockWithData - BlocksForEachTask;
|
||||
|
||||
while (blockIndex < lastFullBlockWithData)
|
||||
{
|
||||
// At this point itemIndex is limited to blockSize range - int.
|
||||
|
||||
// & WAS SLOWER
|
||||
// _ = ThreadPool.QueueUserWorkItem<object?>((_) =>
|
||||
// Task.Factory.StartNew(() =>
|
||||
context.AddParticipant();
|
||||
var startingBlock = blockIndex;
|
||||
_ = Task.Run(() => IndexOfInConsecutiveBlocks(context, list, startingBlock, item));
|
||||
|
||||
// & WAS SLOWER
|
||||
// ScheduleIndexOfTask(context, list, blockIndex, item);
|
||||
if (context._isItemFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
blockIndex += BlocksForEachTask;
|
||||
}
|
||||
|
||||
if (!context._isItemFound)
|
||||
{
|
||||
while (blockIndex < lastBlockWithData)
|
||||
{
|
||||
// & WAS SLOWER
|
||||
// _ = ThreadPool.QueueUserWorkItem<object?>((_) =>
|
||||
// Task.Factory.StartNew(() =>
|
||||
var startingBlock = blockIndex;
|
||||
context.AddParticipant();
|
||||
_ = Task.Run(() => IndexOfIn1Block(context, list, startingBlock, item));
|
||||
|
||||
// & WAS SLOWER
|
||||
// ScheduleIndexOfTaskSingle(context, list, blockIndex, item);
|
||||
if (context._isItemFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
blockIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context._isItemFound)
|
||||
{
|
||||
int itemIndex = list._nextItemIndex != 0
|
||||
? Array.IndexOf(list._memoryBlocks[lastBlockWithData], item, 0, list._nextItemIndex)
|
||||
: Array.IndexOf(list._memoryBlocks[lastBlockWithData], item, 0, list._blockSize);
|
||||
|
||||
if (!context._isItemFound && itemIndex >= 0)
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, lastBlockWithData, ((long)lastBlockWithData << list._blockSizePow2BitShift) + itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
context.SignalAndWait();
|
||||
if (context.Exception == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return context.FoundItemIndex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
context.Exception.CaptureAndReThrow();
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Dispose();
|
||||
}
|
||||
|
||||
return RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static long IndexOfParallel(RecyclableLongList<T> list, T item, int firstBlockIndex, long count)
|
||||
{
|
||||
IndexOfSynchronizationContext context = IndexOfSynchronizationContextPool.GetWithOneParticipant();
|
||||
|
||||
int blockIndex = firstBlockIndex,
|
||||
lastBlockWithData = (int)Math.Min((count >> list._blockSizePow2BitShift) + firstBlockIndex + ((count & list._blockSizeMinus1) > 0 ? 1 : 0) - 1, list._lastBlockWithData),
|
||||
lastFullBlockWithData = lastBlockWithData - BlocksForEachTask;
|
||||
|
||||
while (blockIndex < lastFullBlockWithData)
|
||||
{
|
||||
// At this point itemIndex is limited to blockSize range - int.
|
||||
|
||||
// & WAS SLOWER
|
||||
// _ = ThreadPool.QueueUserWorkItem<object?>((_) =>
|
||||
// Task.Factory.StartNew(() =>
|
||||
context.AddParticipant();
|
||||
var startingBlock = blockIndex;
|
||||
_ = Task.Run(() => IndexOfInConsecutiveBlocks(context, list, startingBlock, item));
|
||||
|
||||
// & WAS SLOWER
|
||||
// ScheduleIndexOfTask(context, list, blockIndex, item);
|
||||
if (context._isItemFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
blockIndex += BlocksForEachTask;
|
||||
}
|
||||
|
||||
if (!context._isItemFound)
|
||||
{
|
||||
count -= (blockIndex - firstBlockIndex) << list._blockSizePow2BitShift;
|
||||
while (blockIndex < lastBlockWithData)
|
||||
{
|
||||
// & WAS SLOWER
|
||||
// _ = ThreadPool.QueueUserWorkItem<object?>((_) =>
|
||||
// Task.Factory.StartNew(() =>
|
||||
var startingBlock = blockIndex;
|
||||
context.AddParticipant();
|
||||
_ = Task.Run(() => IndexOfIn1Block(context, list, startingBlock, item));
|
||||
|
||||
// & WAS SLOWER
|
||||
// ScheduleIndexOfTaskSingle(context, list, blockIndex, item);
|
||||
if (context._isItemFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
blockIndex++;
|
||||
count -= list._blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context._isItemFound && count > 0)
|
||||
{
|
||||
int itemIndex = Array.IndexOf(list._memoryBlocks[lastBlockWithData], item, 0, (int)count);
|
||||
if (!context._isItemFound && itemIndex >= 0)
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, lastBlockWithData, ((long)lastBlockWithData << list._blockSizePow2BitShift) + itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
context.SignalAndWait();
|
||||
if (context.Exception == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return context.FoundItemIndex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
context.Exception.CaptureAndReThrow();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -344,6 +521,119 @@ namespace Recyclable.Collections
|
||||
|
||||
return itemIndex >= 0 ? itemIndex + ((long)list._lastBlockWithData << list._blockSizePow2BitShift) : RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static long IndexOfSequential(RecyclableLongList<T> list, in T item, int firstBlockIndex, long count)
|
||||
{
|
||||
int blockIndex,
|
||||
blockSize = list._blockSize,
|
||||
itemIndex,
|
||||
lastBlockWithData = (int)Math.Min((count >> list._blockSizePow2BitShift) + firstBlockIndex + ((count & list._blockSizeMinus1) > 0 ? 1 : 0) - 1, list._lastBlockWithData);
|
||||
|
||||
byte blockSizePow2BitShift = list._blockSizePow2BitShift;
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = new(list._memoryBlocks, 0, lastBlockWithData + 1);
|
||||
for (blockIndex = firstBlockIndex; blockIndex < lastBlockWithData && count > blockSize; blockIndex += 4)
|
||||
{
|
||||
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)blockIndex << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
count -= blockSize;
|
||||
if (blockIndex + 1 < lastBlockWithData && count > blockSize)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 1], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)(blockIndex + 1) << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
count -= blockSize;
|
||||
if (blockIndex + 2 < lastBlockWithData && count > blockSize)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 2], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)(blockIndex + 2) << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
count -= blockSize;
|
||||
if (blockIndex + 3 < lastBlockWithData && count > blockSize)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 3], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)(blockIndex + 3) << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
count -= blockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[lastBlockWithData], item, 0, (int)count);
|
||||
|
||||
return itemIndex >= 0 ? itemIndex + ((long)lastBlockWithData << blockSizePow2BitShift) : RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static long IndexOfSequential(RecyclableLongList<T> list, in T item, int firstBlockIndex)
|
||||
{
|
||||
int blockIndex,
|
||||
blockSize = list._blockSize,
|
||||
itemIndex,
|
||||
lastBlockWithData = list._lastBlockWithData;
|
||||
|
||||
byte blockSizePow2BitShift = list._blockSizePow2BitShift;
|
||||
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = new(list._memoryBlocks, 0, lastBlockWithData + 1);
|
||||
for (blockIndex = firstBlockIndex; blockIndex < lastBlockWithData; blockIndex += 4)
|
||||
{
|
||||
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)blockIndex << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
if (blockIndex + 1 < lastBlockWithData)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 1], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)(blockIndex + 1) << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
if (blockIndex + 2 < lastBlockWithData)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 2], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)(blockIndex + 2) << blockSizePow2BitShift);
|
||||
}
|
||||
|
||||
if (blockIndex + 3 < lastBlockWithData)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 3], item, 0, blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + ((long)(blockIndex + 3) << blockSizePow2BitShift);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemIndex = list._nextItemIndex != 0
|
||||
? Array.IndexOf(memoryBlocksSpan[lastBlockWithData], item, 0, list._nextItemIndex)
|
||||
: Array.IndexOf(memoryBlocksSpan[lastBlockWithData], item, 0, list._blockSize);
|
||||
|
||||
return itemIndex >= 0 ? itemIndex + ((long)lastBlockWithData << blockSizePow2BitShift) : RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,4 +1,5 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Recyclable.Collections.Pools;
|
||||
@@ -39,7 +40,7 @@ namespace Recyclable.Collections
|
||||
_version++;
|
||||
if (_capacity != value)
|
||||
{
|
||||
_capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)value)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)value)));
|
||||
_version++;
|
||||
}
|
||||
}
|
||||
@@ -61,7 +62,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)initialCapacity)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)initialCapacity)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
}
|
||||
@@ -74,7 +75,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.LongLength)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.LongLength)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -89,7 +90,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.LongLength)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.LongLength)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -104,7 +105,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -119,7 +120,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Length)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Length)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -134,7 +135,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -149,7 +150,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -164,7 +165,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Length)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Length)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -179,7 +180,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -194,7 +195,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -209,7 +210,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)source.Count)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -224,7 +225,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)initialCapacity)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)initialCapacity)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -239,7 +240,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)minBlockSize));
|
||||
_capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)initialCapacity)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, minBlockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)initialCapacity)));
|
||||
_blockSize = minBlockSize;
|
||||
_blockSizeMinus1 = minBlockSize - 1;
|
||||
|
||||
@@ -273,7 +274,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
if (_capacity < _longCount + 1)
|
||||
{
|
||||
_capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(_longCount + 1))));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(_longCount + 1))));
|
||||
}
|
||||
|
||||
_memoryBlocks[_nextItemBlockIndex][_nextItemIndex++] = item;
|
||||
@@ -374,7 +375,7 @@ namespace Recyclable.Collections
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int itemIndex = Array.IndexOf(_memoryBlocks[0], item, 0, _longCount < _blockSize ? _nextItemIndex : _blockSize);
|
||||
int itemIndex = Array.IndexOf(_memoryBlocks[0], item, 0, _blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex;
|
||||
@@ -397,6 +398,104 @@ namespace Recyclable.Collections
|
||||
}
|
||||
}
|
||||
|
||||
public int IndexOf(T item, int index)
|
||||
{
|
||||
if (index < 0 || index >= _longCount)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||
}
|
||||
|
||||
Contract.Requires(index >= 0);
|
||||
Contract.Requires(index < _longCount);
|
||||
Contract.EndContractBlock();
|
||||
|
||||
if (_lastBlockWithData == 0)
|
||||
{
|
||||
return Array.IndexOf(_memoryBlocks[0], item, index, (_longCount < _blockSize ? _nextItemIndex : _blockSize) - index);
|
||||
}
|
||||
else if (_longCount == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int firstBlockIndex = index >> _blockSizePow2BitShift;
|
||||
int firstItemIndex = index & _blockSizeMinus1;
|
||||
int itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex], item, firstItemIndex, (firstBlockIndex == _lastBlockWithData && _nextItemIndex > 0 ? _nextItemIndex : _blockSize) - firstItemIndex);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return (firstBlockIndex << _blockSizePow2BitShift) + itemIndex;
|
||||
}
|
||||
else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization && firstBlockIndex + 1 <= _lastBlockWithData)
|
||||
{
|
||||
return (int)RecyclableLongList<T>.IndexOfHelpers.IndexOfSequential(this, item, firstBlockIndex + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (firstBlockIndex + 1 <= _lastBlockWithData)
|
||||
{
|
||||
itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex + 1], item, 0, (int)Math.Min(firstBlockIndex + 1 == _lastBlockWithData ? _nextItemIndex : _blockSize, _longCount - _blockSize));
|
||||
return itemIndex >= 0 ? ((firstBlockIndex + 1) << _blockSizePow2BitShift) + itemIndex : checked((int)RecyclableLongList<T>.IndexOfHelpers.IndexOfParallel(this, item, firstBlockIndex + 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int IndexOf(T item, int index, int count)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||
}
|
||||
|
||||
if (count + index > _longCount)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Count();
|
||||
}
|
||||
|
||||
Contract.Requires(index >= 0);
|
||||
Contract.Requires(count + index <= _longCount);
|
||||
Contract.EndContractBlock();
|
||||
|
||||
if (_lastBlockWithData == 0)
|
||||
{
|
||||
return Array.IndexOf(_memoryBlocks[0], item, index, count);
|
||||
}
|
||||
else if (_longCount == 0 || count == 0)
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
int blockSize = _blockSize,
|
||||
firstBlockIndex = index >> _blockSizePow2BitShift,
|
||||
firstItemIndex = index & _blockSizeMinus1;
|
||||
|
||||
int firstBlockItemsCount = Math.Min(blockSize - firstItemIndex, count);
|
||||
int itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex], item, firstItemIndex, firstBlockItemsCount);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return (firstBlockIndex << _blockSizePow2BitShift) + itemIndex;
|
||||
}
|
||||
else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization && firstBlockIndex + 1 <= _lastBlockWithData)
|
||||
{
|
||||
return (int)RecyclableLongList<T>.IndexOfHelpers.IndexOfSequential(this, item, firstBlockIndex + 1, count - firstBlockItemsCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (firstBlockIndex + 1 <= _lastBlockWithData)
|
||||
{
|
||||
itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex + 1], item, 0, (int)MathUtils.Min(blockSize, _longCount - blockSize, count - firstBlockItemsCount));
|
||||
return itemIndex >= 0 ? ((firstBlockIndex + 1) << _blockSizePow2BitShift) + itemIndex : checked((int)RecyclableLongList<T>.IndexOfHelpers.IndexOfParallel(this, item, firstBlockIndex + 2, count - firstBlockItemsCount - blockSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
if (index > _longCount || index < 0)
|
||||
@@ -406,7 +505,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (_capacity < ++_longCount)
|
||||
{
|
||||
_capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)_longCount)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)_longCount)));
|
||||
}
|
||||
|
||||
if (index + 1 < _longCount)
|
||||
@@ -445,7 +544,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (_capacity < ++_longCount)
|
||||
{
|
||||
_capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)_longCount)));
|
||||
_capacity = Helpers.Resize(ref _memoryBlocks, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)_longCount)));
|
||||
}
|
||||
|
||||
if (index + 1 < _longCount)
|
||||
|
||||
@@ -150,9 +150,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
RemoveBlock(Memory._count - 1);
|
||||
}
|
||||
#pragma warning disable RCS1075 // We want to try returning as many arrays, as possible, before the list is cleared.
|
||||
catch (Exception)
|
||||
#pragma warning restore RCS1075
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
#pragma warning disable IDE0022, CA2208
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
internal static class ThrowHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a helper method to throw <see cref="ArgumentOutOfRangeException"/> with the given message.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Always</exception>
|
||||
public static void ThrowArgumentException(string argumentName) => throw new ArgumentException("Parameter has invalid value. ", argumentName);
|
||||
public static void ThrowArgumentException(string argumentName, Exception? innerException) => throw new ArgumentException("Parameter has invalid value. ", argumentName, innerException);
|
||||
public static void ThrowArgumentException(string argumentName, string message) => throw new ArgumentException(message, argumentName);
|
||||
public static void ThrowArgumentException(string argumentName, string message, Exception? innerException) => throw new ArgumentException(message, argumentName, innerException);
|
||||
public static void ThrowArgumentException_Index() => throw new ArgumentException("Parameter has invalid value", "index");
|
||||
public static void ThrowArgumentException_Index(Exception? innerException) => throw new ArgumentException("Parameter has invalid value", "index", innerException);
|
||||
public static void ThrowArgumentException_Count() => throw new ArgumentException("Parameter has invalid value", "count");
|
||||
public static void ThrowArgumentException_Count(Exception? innerException) => throw new ArgumentException("Parameter has invalid value", "count", innerException);
|
||||
public static void ThrowArgumentOutOfRangeException(string argumentName) => throw new ArgumentOutOfRangeException(argumentName);
|
||||
public static void ThrowArgumentOutOfRangeException(string argumentName, Exception? innerException) => throw new ArgumentOutOfRangeException($"Argument {argumentName} is out of range", innerException);
|
||||
public static void ThrowArgumentOutOfRangeException(string argumentName, string message) => throw new ArgumentOutOfRangeException(argumentName, message);
|
||||
public static void ThrowWrongReturnedArraySizeException(int returnedLength, int blockSize) => throw new InvalidOperationException($"The array size {returnedLength} doesn't match the size {blockSize} of the pool buffer and cannot be returned to this pool.");
|
||||
public static void ThrowArgumentOutOfRangeException_Index() => throw new ArgumentOutOfRangeException("index", "Parameter `index` has invalid value. It must be within the no. of elements in the collection");
|
||||
public static void ThrowArgumentOutOfRangeException_Count() => throw new ArgumentOutOfRangeException("index", "Parameter `count` has invalid value. Combined with index, it must be within the no. of elements in the collection");
|
||||
public static void ThrowArgumentOutOfRangeException_Index(Exception? innerException) => throw new ArgumentOutOfRangeException("Parameter `index` has invalid value. It must be within the no. of elements in the collection", innerException);
|
||||
public static void ThrowArgumentOutOfRangeException_Count() => throw new ArgumentOutOfRangeException("count", "Parameter `count` has invalid value. Combined with index, it must be within the no. of elements in the collection");
|
||||
public static void ThrowArgumentOutOfRangeException_Count(Exception? innerException) => throw new ArgumentOutOfRangeException("Parameter `count` has invalid value. Combined with index, it must be within the no. of elements in the collection", innerException);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public class CustomIList<T> : IList<T>
|
||||
{
|
||||
protected List<T> _list;
|
||||
|
||||
public CustomIList()
|
||||
{
|
||||
_list = new List<T>();
|
||||
}
|
||||
|
||||
public CustomIList(IEnumerable<T> items)
|
||||
{
|
||||
_list = new List<T>(items);
|
||||
}
|
||||
|
||||
public T this[int index] { get => _list[index]; set => _list[index] = value; }
|
||||
public int Count => _list.Count;
|
||||
public bool IsReadOnly => false;
|
||||
public void Add(T item) => _list.Add(item);
|
||||
public void Clear() => _list.Clear();
|
||||
public bool Contains(T item) => _list.Contains(item);
|
||||
public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(0, array, arrayIndex, _list.Count);
|
||||
public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
|
||||
public int IndexOf(T item) => _list.IndexOf(item);
|
||||
public void Insert(int index, T item) => _list.Insert(index, item);
|
||||
public bool Remove(T item) => _list.Remove(item);
|
||||
public void RemoveAt(int index) => _list.RemoveAt(index);
|
||||
IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public class EnumerableWithoutCount<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly IEnumerable<T> _testData;
|
||||
|
||||
public EnumerableWithoutCount(IEnumerable<T> testData)
|
||||
{
|
||||
_testData = testData;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => _testData.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => _testData.GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using FluentAssertions;
|
||||
// Ignore Spelling: Utils
|
||||
|
||||
using FluentAssertions;
|
||||
using Recyclable.Collections;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
|
||||
@@ -9,20 +9,21 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Open.Numeric.Primes" Version="3.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.5.0">
|
||||
<PackageReference Include="Recyclable.Collections.TestData" Version="0.0.3.5" />
|
||||
<PackageReference Include="Recyclable.Collections.TestData.xUnit" Version="0.0.0.2" />
|
||||
<PackageReference Include="xunit" Version="2.6.4" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.6.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,282 +0,0 @@
|
||||
using MoreLinq;
|
||||
using Open.Numeric.Primes;
|
||||
using Recyclable.Collections;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public static class RecyclableLongListTestData
|
||||
{
|
||||
|
||||
private static readonly object[] _sourceRefData = Enumerable.Range(1, 100).Cast<object>().ToArray();
|
||||
public static object[] SourceRefData => _sourceRefData;
|
||||
|
||||
public static IEnumerable<long> CreateTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object> CreateRefTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly IEnumerable<long> ItemsCountVariants = new long[]
|
||||
{
|
||||
//RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, 127, 128, 129, RecyclableDefaults.MinItemsCountForParallelization
|
||||
0, 1, 2, 3, 7, 10, 16, RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, RecyclableDefaults.MinPooledArrayLength * 100
|
||||
};
|
||||
|
||||
public static readonly IEnumerable<object[]> ItemsCountTestCases = ItemsCountVariants.Select(x => new object[] { (int)x });
|
||||
|
||||
public static readonly IEnumerable<int> BlockSizeVariants = new int[]
|
||||
{
|
||||
1, 2, 4, 16, RecyclableDefaults.MinPooledArrayLength - 5, (int)BitOperations.RoundUpToPowerOf2(RecyclableDefaults.MinPooledArrayLength)
|
||||
};
|
||||
|
||||
private static bool IsValidBlockSize(long itemsCount, long blockSize) => itemsCount is < 1024 || blockSize is > 8;
|
||||
|
||||
private static IEnumerable<object[]> GetTargetDataVariants()
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { itemsCount, targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TargetDataVariants => GetTargetDataVariants();
|
||||
|
||||
private static IEnumerable<object[]> CombineSourceDataWithBlockSize(IEnumerable<object[]> sourceData)
|
||||
{
|
||||
foreach (var testData in sourceData)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize((long)testData[2], targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { testData[0], testData[1], testData[2], targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(long itemsCount, bool refType)
|
||||
{
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
switch (refType)
|
||||
{
|
||||
case false:
|
||||
long[] testData = CreateTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"Array[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"ICollection[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"ICollection<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable<T>[{itemsCount}] without non-enumerated count", new EnumerableWithoutCount<long>(testData), itemsCount };
|
||||
yield return new object[] { $"IList<T>[{itemsCount}]", new CustomIList<long>(testData), itemsCount };
|
||||
yield return new object[] { $"IReadOnlyList<T>[{itemsCount}])", testData, itemsCount };
|
||||
yield return new object[] { $"List<T>[{itemsCount}]", testData.ToList(), itemsCount };
|
||||
yield return new object[] { $"ReadOnlySpan<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"RecyclableList<T>[{itemsCount}]", testData.ToRecyclableList(), itemsCount };
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<T>[itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize}]",
|
||||
testData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"Span<T>[{itemsCount}]", testData, itemsCount };
|
||||
yield return new object[] { $"T[{itemsCount}]", testData, itemsCount };
|
||||
break;
|
||||
|
||||
case true:
|
||||
IEnumerable<object> testRefData = CreateRefTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"Array[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"ICollection(itemsCount: {itemsCount}", testRefData, itemsCount };
|
||||
yield return new object[] { $"ICollection<T>(itemsCount: {itemsCount}", testRefData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable(itemsCount: {itemsCount})", testRefData, itemsCount };
|
||||
yield return new object[] { $"IEnumerable<T>(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount<object>(testRefData), itemsCount };
|
||||
yield return new object[] { $"IList<T>(itemsCount: {itemsCount})", new CustomIList<object>(testRefData), itemsCount };
|
||||
yield return new object[] { $"IReadOnlyList<T>(itemsCount: {itemsCount})", testRefData, itemsCount };
|
||||
yield return new object[] { $"List<T>(itemsCount: {itemsCount}", testRefData.ToList(), itemsCount };
|
||||
yield return new object[] { $"ReadOnlySpan<T>[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"RecyclableList<T>(itemsCount: {itemsCount})", testRefData.ToRecyclableList(), itemsCount };
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<T>(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})",
|
||||
testRefData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"Span<T>[{itemsCount}]", testRefData, itemsCount };
|
||||
yield return new object[] { $"T[{itemsCount}]", testRefData, itemsCount };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(bool refType)
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var variant in CreateSourceDataVariants(itemsCount, refType))
|
||||
{
|
||||
yield return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> EmptySourceDataVariants => CreateSourceDataVariants(0, false);
|
||||
public static IEnumerable<object[]> SourceDataVariants => CreateSourceDataVariants(false);
|
||||
public static IEnumerable<object[]> SourceDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var testCase in CreateSourceDataVariants(false).Where(testCase => (long)testCase[2] > 0))
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceRefDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<object[]> testCases = CreateSourceDataVariants(true).Where(testCase => (long)testCase[2] > 0);
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeVariants => CombineSourceDataWithBlockSize(SourceDataVariants);
|
||||
public static IEnumerable<object[]> SourceRefDataVariants => CreateSourceDataVariants(true);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeVariants { get; } = CombineSourceDataWithBlockSize(SourceRefDataVariants);
|
||||
|
||||
private static IEnumerable<long> _initialItemIndexVariants => new long[] { 0, 1, 2, 3, 4, 5 };
|
||||
private static IEnumerable<long> CreateItemIndexVariants(long itemsCount, int blockSize)
|
||||
{
|
||||
IEnumerable<long> primes = _initialItemIndexVariants.Concat(
|
||||
_initialItemIndexVariants.SelectMany(index => new long[] { blockSize - index, blockSize + index })
|
||||
//new long[] { blockSize - 3, blockSize - 2, blockSize - 1, blockSize, blockSize + 1, blockSize + 2, blockSize + 3 }
|
||||
).ToArray();
|
||||
|
||||
IEnumerable<long> second = Prime.Numbers.StartingAt(7)
|
||||
.TakeUntil(prime =>
|
||||
prime > ((blockSize * 2) - 1) ||
|
||||
prime >= itemsCount
|
||||
);
|
||||
|
||||
primes = primes.Concat(second).ToArray();
|
||||
|
||||
primes = primes.Concat(
|
||||
primes.Select(index => itemsCount - index - 1)
|
||||
)
|
||||
.Where(index => itemsCount > 0 && index >= 0 && index < itemsCount).ToArray()
|
||||
.Distinct().ToArray();
|
||||
|
||||
return primes;
|
||||
|
||||
//IEnumerable<long> CreateItemIndexVariants()
|
||||
//{
|
||||
//if (itemsCount > 0)
|
||||
//{
|
||||
// yield return 0;
|
||||
//}
|
||||
|
||||
//foreach (long prime in primes)
|
||||
//{
|
||||
// yield return prime;
|
||||
|
||||
// long index = itemsCount - prime;
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//for (long index = itemsCount - (blockSize * 2) - 1; index < itemsCount; index++)
|
||||
//{
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if ((blockSize / 16 * 16) + 1 < itemsCount)
|
||||
//{
|
||||
// yield return (blockSize / 16 * 16) + 1;
|
||||
//}
|
||||
//}
|
||||
|
||||
//return CreateItemIndexVariants();
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CombineSourceRefDataWithBlockSizeWithItemIndex(bool refType)
|
||||
{
|
||||
IEnumerable<object[]> sourceData = refType switch
|
||||
{
|
||||
false => SourceDataWithBlockSizeVariants,
|
||||
true => SourceRefDataWithBlockSizeVariants
|
||||
};
|
||||
|
||||
foreach (var testCase in sourceData)
|
||||
{
|
||||
long itemsCount = (long)testCase[2];
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
long[] itemIndexes = CreateItemIndexVariants(itemsCount, (int)testCase[3])
|
||||
.Where(_ => IsValidBlockSize((long)testCase[2], (int)testCase[3]))
|
||||
.ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], (long)testCase[2], (int)testCase[3], itemIndexes };
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(false);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(true);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
using FluentAssertions;
|
||||
using Recyclable.Collections;
|
||||
using Recyclable.Collections.TestData;
|
||||
using Recyclable.Collections.Linq;
|
||||
using System.Collections;
|
||||
using System.Numerics;
|
||||
using Recyclable.Collections.TestData.xUnit;
|
||||
using Open.Collections;
|
||||
|
||||
#pragma warning disable xUnit1026, RCS1163, IDE0060, RCS1235
|
||||
|
||||
@@ -35,7 +38,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void AddRangeShouldAddItemsInCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -108,7 +111,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(EmptySourceDataTheoryData))]
|
||||
public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
@@ -180,11 +183,11 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void AddRangeShouldNotOverrideItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(minBlockSize: targetBlockSize);
|
||||
using RecyclableLongList<long> list = new(minBlockSize: targetBlockSize);
|
||||
|
||||
// Act
|
||||
if (testCase.Contains("Array[", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -268,7 +271,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void AddShouldAcceptDuplicates(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -306,7 +309,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void AddShouldAddItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -327,7 +330,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
//[InlineData("Debugging case", new long[1] { 1 }, 1, 2)]
|
||||
public void AddShouldAddItemWhenAfterAddRange(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
@@ -347,7 +350,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceRefDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceRefDataWithBlockSizeTheoryData))]
|
||||
public void ClearShouldClearItemsWhenReferenceType(string testCase, IEnumerable<object> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
@@ -373,7 +376,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void ClearShouldRemoveAllItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -411,7 +414,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void ConsecutiveDisposeShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -423,7 +426,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void ConstructorShouldAcceptDuplicates(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -440,7 +443,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void ConstructorSourceShouldInitializeList(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Act
|
||||
@@ -454,7 +457,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void ContainsShouldFindAllItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
@@ -469,7 +472,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.TargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(ItemsCountWithBlockSizeTheoryData))]
|
||||
public void ContainsShouldNotFindAnythingWhenListEmpty(long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -481,7 +484,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void ContainsShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
@@ -496,7 +499,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
//[InlineData("Debugging case", new[] { 1L, 2, }, 2, 2)]
|
||||
public void CopyToShouldCopyAllItemsInTheCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
@@ -512,7 +515,36 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceRefDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenConstrainedRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
var expectedData = testData.ToList();
|
||||
TestCopyTo(0);
|
||||
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
TestCopyTo((int)itemIndex);
|
||||
TestCopyTo((int)itemIndex);
|
||||
}
|
||||
|
||||
void TestCopyTo(int itemIndex)
|
||||
{
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize, initialCapacity: itemsCount);
|
||||
long[] expectedItems = new long[itemsCount + itemIndex];
|
||||
expectedData.CopyTo(expectedItems, itemIndex);
|
||||
long[] actualItems = new long[itemsCount + itemIndex];
|
||||
|
||||
// Act
|
||||
list.CopyTo(actualItems, itemIndex);
|
||||
|
||||
// Validate
|
||||
_ = actualItems.Should().Equal(expectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SourceRefDataWithBlockSizeTheoryData))]
|
||||
public void DisposeShouldClearItemsWhenReferenceType(string testCase, IEnumerable<object> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
@@ -556,7 +588,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void DisposeShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -573,7 +605,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void EnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable<long> testData, int itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -592,7 +624,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void GetByIndexShouldReturnCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -606,7 +638,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void GetByIndexShouldReturnCorrectItemWhenLong(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -619,6 +651,188 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BigSourceDataWithOutOfRangeItemIndexesWithRangeTheoryData))]
|
||||
public void IndexOfParallelShouldNotFindAnythingWhenBeyondRange(string testCase, IEnumerable<long> testData, long itemsCount, int blockSize, IEnumerable<(long itemIndex, long rangeStartItemIndex, long rangeItemsCount)> itemIndexesWithRanges)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: itemsCount);
|
||||
using var expectedData = testData.ToRecyclableLongList();
|
||||
|
||||
foreach (var (itemIndex, rangeStartItemIndex, rangedItemsCount) in itemIndexesWithRanges)
|
||||
{
|
||||
// Act & Validate
|
||||
_ = list.IndexOf(expectedData[itemIndex], (int)rangeStartItemIndex, (int)rangedItemsCount).Should().Be(-1);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BlockSizeTheoryData))]
|
||||
public void IndexOfParallelShouldNotFindNonExistingItems(int blockSize)
|
||||
{
|
||||
const long ItemsCount = RecyclableDefaults.MinItemsCountForParallelization * 3;
|
||||
|
||||
// Prepare
|
||||
var testData = RecyclableLongListTestData.CreateTestData(ItemsCount).ToList();
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: ItemsCount);
|
||||
|
||||
// Act & Validate
|
||||
_ = list.IndexOf(0).Should().Be(-1);
|
||||
|
||||
var itemIndexes = RecyclableLongListTestData.CreateItemIndexVariants(ItemsCount, blockSize);
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
var item = -testData[(int)itemIndex];
|
||||
|
||||
// Act & Validate
|
||||
_ = list.IndexOf(item).Should().Be(-1);
|
||||
_ = list.IndexOf(item, (int)itemIndex).Should().Be(-1);
|
||||
_ = list.IndexOf(-item, (int)itemIndex, 0).Should().Be(-1);
|
||||
_ = list.IndexOf(0, (int)itemIndex).Should().Be(-1);
|
||||
_ = list.IndexOf(0, (int)itemIndex, 0).Should().Be(-1);
|
||||
_ = list.IndexOf(item, (int)ItemsCount, 0).Should().Be(-1);
|
||||
|
||||
if (itemIndex > 0)
|
||||
{
|
||||
_ = list.IndexOf(testData[(int)itemIndex - 1], (int)itemIndex).Should().Be(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BlockSizeTheoryData))]
|
||||
public void IndexOfParallelShouldNotFindNonExistingItemsWhenConstrainedCount(int blockSize)
|
||||
{
|
||||
const long ItemsCount = RecyclableDefaults.MinItemsCountForParallelization * 3;
|
||||
|
||||
// Prepare
|
||||
var testData = RecyclableLongListTestData.CreateTestData(ItemsCount).ToArray();
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: ItemsCount);
|
||||
|
||||
var itemIndexes = RecyclableLongListTestData.CreateItemIndexVariants(ItemsCount, blockSize);
|
||||
foreach (var itemIndexForGenerator in itemIndexes)
|
||||
{
|
||||
var itemRanges = RecyclableLongListTestData.CombineItemIndexWithRange(itemIndexForGenerator, ItemsCount);
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||
{
|
||||
// Act & Validate
|
||||
_ = list.IndexOf(-testData[itemIndex], (int)itemIndex, (int)rangedItemsCount).Should().Be(-1);
|
||||
_ = list.IndexOf(0, (int)itemIndex, (int)rangedItemsCount).Should().Be(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BlockSizeTheoryData))]
|
||||
public void IndexOfParallelShouldReturnCorrectIndexes(int blockSize)
|
||||
{
|
||||
const long ItemsCount = RecyclableDefaults.MinItemsCountForParallelization * 3;
|
||||
|
||||
// Prepare
|
||||
var testData = RecyclableLongListTestData.CreateTestData(ItemsCount).ToArray();
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: ItemsCount);
|
||||
|
||||
// Act & Validate
|
||||
IEnumerable<long> itemIndexes = RecyclableLongListTestData.CreateItemIndexVariants(ItemsCount, blockSize);
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
var actual = list.IndexOf(testData[itemIndex]);
|
||||
_ = actual.Should().Be((int)itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BlockSizeTheoryData))]
|
||||
public void IndexOfParallelShouldReturnCorrectIndexesWhenConstrainedCount(int blockSize)
|
||||
{
|
||||
const long ItemsCount = RecyclableDefaults.MinItemsCountForParallelization * 3;
|
||||
|
||||
// Prepare
|
||||
var testData = RecyclableLongListTestData.CreateTestData(ItemsCount).ToArray();
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: ItemsCount);
|
||||
|
||||
var itemIndexes = RecyclableLongListTestData.CreateItemIndexVariants(ItemsCount, blockSize);
|
||||
foreach (var itemIndexForGenerator in itemIndexes)
|
||||
{
|
||||
var itemRanges = RecyclableLongListTestData.CombineItemIndexWithRange(itemIndexForGenerator, ItemsCount);
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||
{
|
||||
// Act & Validate
|
||||
if (rangedItemsCount > 0)
|
||||
{
|
||||
// Find first item in range
|
||||
_ = list.IndexOf(testData[itemIndex], (int)itemIndex, (int)rangedItemsCount).Should().Be((int)itemIndex);
|
||||
|
||||
// Find last item in range
|
||||
_ = list.IndexOf(testData[itemIndex + rangedItemsCount - 1], (int)itemIndex, (int)rangedItemsCount).Should().Be((int)(itemIndex + rangedItemsCount - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BlockSizeTheoryData))]
|
||||
public void IndexOfParallelShouldReturnCorrectIndexesWhenConstrainedIndex(int blockSize)
|
||||
{
|
||||
const long ItemsCount = RecyclableDefaults.MinItemsCountForParallelization * 3;
|
||||
|
||||
// Prepare
|
||||
var testData = RecyclableLongListTestData.CreateTestData(ItemsCount).ToArray();
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: ItemsCount);
|
||||
|
||||
var itemIndexes = RecyclableLongListTestData.CreateItemIndexVariants(ItemsCount, blockSize);
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
_ = list.IndexOf(testData[itemIndex], (int)itemIndex).Should().Be((int)itemIndex);
|
||||
_ = list.IndexOf(testData[^1], (int)itemIndex).Should().Be(list.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(BlockSizeTheoryData))]
|
||||
public void IndexOfParallelShouldThrowWhenInvalidRange(int blockSize)
|
||||
{
|
||||
const long ItemsCount = RecyclableDefaults.MinItemsCountForParallelization * 3;
|
||||
|
||||
// Prepare
|
||||
var testData = RecyclableLongListTestData.CreateTestData(ItemsCount).ToList();
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: ItemsCount);
|
||||
|
||||
var item = testData[0];
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => testData.IndexOf(item, -1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.IndexOf(item, -1));
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => testData.IndexOf(item, (int)ItemsCount + 1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.IndexOf(item, (int)ItemsCount + 1));
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => testData.IndexOf(item, (int)ItemsCount, 1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.IndexOf(item, (int)ItemsCount, 1));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexWithRangeTheoryData))]
|
||||
public void IndexOfShouldNotFindAnythingWhenBeyondRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: minBlockSize, initialCapacity: itemsCount);
|
||||
var expectedData = testData.ToArray();
|
||||
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||
{
|
||||
// Try finding the item prior the given itemIndex
|
||||
if (itemIndex > 0)
|
||||
{
|
||||
_ = list.IndexOf(expectedData[(int)(itemIndex - 1)], (int)itemIndex, (int)rangedItemsCount).Should().Be(-1);
|
||||
}
|
||||
|
||||
// Try finding the item after the given item range
|
||||
if (itemIndex + rangedItemsCount < itemsCount)
|
||||
{
|
||||
_ = list.IndexOf(expectedData[(int)(itemIndex + rangedItemsCount)], (int)itemIndex, (int)rangedItemsCount).Should().Be(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOfShouldNotFindAnythingWhenListEmpty()
|
||||
{
|
||||
@@ -631,22 +845,36 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void IndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
var expectedData = testData.ToArray();
|
||||
|
||||
// Act & Validate
|
||||
_ = list.IndexOf(0).Should().Be(-1);
|
||||
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
_ = list.IndexOf(-list[itemIndex]).Should().Be(-1);
|
||||
var item = -expectedData[itemIndex];
|
||||
|
||||
_ = list.IndexOf(item).Should().Be(-1);
|
||||
_ = list.IndexOf(item, (int)itemIndex).Should().Be(-1);
|
||||
_ = list.IndexOf(-item, (int)itemIndex, 0).Should().Be(-1);
|
||||
_ = list.IndexOf(0, (int)itemIndex).Should().Be(-1);
|
||||
_ = list.IndexOf(0, (int)itemIndex, 0).Should().Be(-1);
|
||||
|
||||
if (itemIndex > 0)
|
||||
{
|
||||
_ = list.IndexOf(list[itemIndex - 1], (int)itemIndex).Should().Be(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void IndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
@@ -655,12 +883,51 @@ namespace Recyclable.CollectionsTests
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
_ = list.IndexOf(list[itemIndex]).Should().Be((int)itemIndex);
|
||||
int actual = list.IndexOf(list[itemIndex]);
|
||||
_ = actual.Should().Be((int)itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexWithRangeTheoryData))]
|
||||
public void IndexOfShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: minBlockSize, itemsCount);
|
||||
var expectedData = testData.ToList();
|
||||
|
||||
// Act & Validate
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||
{
|
||||
// Act & Validate
|
||||
if (rangedItemsCount > 0)
|
||||
{
|
||||
// Find first item in range
|
||||
_ = list.IndexOf(expectedData[(int)itemIndex], (int)itemIndex, (int)rangedItemsCount).Should().Be((int)itemIndex);
|
||||
|
||||
// Find last item in range
|
||||
_ = list.IndexOf(expectedData[(int)(itemIndex + rangedItemsCount - 1)], (int)itemIndex, (int)rangedItemsCount).Should().Be((int)(itemIndex + rangedItemsCount - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void IndexOfShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable<long> testData, long itemsCount, int blockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: blockSize, initialCapacity: itemsCount);
|
||||
var expectedData = testData.ToList();
|
||||
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
_ = list.IndexOf(expectedData[(int)itemIndex], (int)itemIndex).Should().Be((int)itemIndex);
|
||||
_ = list.IndexOf(expectedData[^1], (int)itemIndex).Should().Be(list.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
@@ -704,7 +971,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void InsertShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
|
||||
@@ -732,7 +999,86 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexWithRangeTheoryData))]
|
||||
public void InsertRangeShouldMoveItems(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges)
|
||||
{
|
||||
// Prepare
|
||||
var expectedData = testData.Reverse().ToArray();
|
||||
|
||||
foreach ((var itemIndex, var rangedItemsCount) in itemRanges)
|
||||
{
|
||||
using var list = new RecyclableLongList<long>(testData.Reverse(), minBlockSize, itemsCount);
|
||||
var expected = expectedData.ToList();
|
||||
var rangedTestData = expected.GetRange((int)itemIndex, (int)rangedItemsCount).ToArray();
|
||||
expected.InsertRange((int)itemIndex, rangedTestData);
|
||||
|
||||
if (testCase.Contains("Array[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, (Array)rangedTestData);
|
||||
}
|
||||
else if (testCase.Contains("ICollection[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, (ICollection)rangedTestData);
|
||||
}
|
||||
else if (testCase.Contains("ICollection<T>[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, (ICollection<long>)rangedTestData);
|
||||
}
|
||||
else if (testCase.Contains("IEnumerable[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, (IEnumerable)rangedTestData);
|
||||
}
|
||||
else if (testCase.Contains("IReadOnlyList<T>[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, (IReadOnlyList<long>)rangedTestData);
|
||||
}
|
||||
else if (testCase.Contains("ReadOnlySpan<T>[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, new ReadOnlySpan<long>(rangedTestData));
|
||||
}
|
||||
else if (testCase.Contains("Span<T>[", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.InsertRange((int)itemIndex, new Span<long>(rangedTestData));
|
||||
}
|
||||
else if (testData is long[] testDataArray)
|
||||
{
|
||||
list.InsertRange((int)itemIndex, rangedTestData);
|
||||
}
|
||||
else if (testData is List<long> testDataList)
|
||||
{
|
||||
list.InsertRange((int)itemIndex, rangedTestData.ToList());
|
||||
}
|
||||
else if (testData is RecyclableList<long> testDataRecyclableList)
|
||||
{
|
||||
using RecyclableList<long> rangedTestDataRecyclableList = rangedTestData.ToRecyclableList();
|
||||
list.InsertRange((int)itemIndex, rangedTestDataRecyclableList);
|
||||
}
|
||||
else if (testData is RecyclableLongList<long> testDataRecyclableLongList)
|
||||
{
|
||||
using RecyclableLongList<long> rangedTestDataRecyclableList = rangedTestData.ToRecyclableLongList();
|
||||
list.InsertRange((int)itemIndex, rangedTestDataRecyclableList);
|
||||
}
|
||||
else if (testData is IList<long> testDataIList)
|
||||
{
|
||||
list.InsertRange((int)itemIndex, (IList<long>)rangedTestData);
|
||||
}
|
||||
else if (testData is IEnumerable<long> testDataIEnumerable)
|
||||
{
|
||||
list.InsertRangeEnumerated((int)itemIndex, (IEnumerable<long>)rangedTestData);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidCastException("Unknown type of test data");
|
||||
}
|
||||
|
||||
// Validate
|
||||
list.Count.Should().Be(expected.Count);
|
||||
_ = list.Should().Equal(expected);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void InsertShouldMoveItemsWhenLong(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
|
||||
@@ -771,7 +1117,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void LongIndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
@@ -786,7 +1132,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void LongIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
@@ -800,7 +1146,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceRefDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceRefDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void RemoveAtShouldClearItemWhenReferenceType(string testCase, IEnumerable<object> testData, long itemsCount, int targetBlockSize, in long[] indexesToRemove)
|
||||
{
|
||||
foreach (var indexToRemove in indexesToRemove)
|
||||
@@ -818,7 +1164,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void RemoveAtShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
@@ -840,7 +1186,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void RemoveAtShouldRemoveTheCorrectItemWhenLong(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
@@ -862,7 +1208,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceRefDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceRefDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void RemoveShouldClearItemWhenReferenceType(string testCase, IEnumerable<object> testData, long itemsCount, int targetBlockSize, in long[] indexesToRemove)
|
||||
{
|
||||
var expectedItems = testData.ToArray();
|
||||
@@ -883,7 +1229,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeWithItemIndexTheoryData))]
|
||||
public void RemoveShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
@@ -906,7 +1252,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void SetByIndexShouldReturnCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -927,7 +1273,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void SetByIndexShouldReturnCorrectItemWhenLong(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -948,7 +1294,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void VersionedEnumerateShouldRaiseExceptionWhenCollectionIsModified(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -968,7 +1314,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[ClassData(typeof(SourceDataWithBlockSizeTheoryData))]
|
||||
public void VersionedEnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable<long> testData, int itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DequeueShoudRaiseArgumentOutOfRangeWhenNoMoreElementsFound()
|
||||
public void DequeueShouldRaiseArgumentOutOfRangeWhenNoMoreElementsFound()
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableQueue<string>(_testData);
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopShoudRaiseArgumentOutOfRangeWhenNoMoreElementsFound()
|
||||
public void PopShouldRaiseArgumentOutOfRangeWhenNoMoreElementsFound()
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableQueue<string>(_testData);
|
||||
|
||||
Reference in new issue
Block a user