RecyclableList performance optimizations.

This commit is contained in:
mlemanczyk committed 2023-01-23 01:22:41 +01:00
1 parent 30dfd97336
commit f45b6aac98
1 file changed
+40 -12
+40 -12
View File
@@ -11,7 +11,7 @@ namespace Recyclable.Collections
private static readonly T[][] _emptyBlockArray = new T[0][]; private static readonly T[][] _emptyBlockArray = new T[0][];
private static readonly IEqualityComparer<T> _equalityComparer = EqualityComparer<T>.Default; private static readonly IEqualityComparer<T> _equalityComparer = EqualityComparer<T>.Default;
private readonly int _blockSize; private int _blockSize;
protected T[][] _memoryBlocks; protected T[][] _memoryBlocks;
private long _capacity; private long _capacity;
@@ -58,7 +58,7 @@ namespace Recyclable.Collections
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
protected static T[][] SetNewLength(in T[][]? source, in int blockSize, in long newCapacity) protected static T[][] SetNewLength(in T[][]? source, int blockSize, in long newCapacity)
{ {
ArrayPool<T[]> arrayPool = _arrayPool; ArrayPool<T[]> arrayPool = _arrayPool;
ArrayPool<T> blockArrayPool = _blockArrayPool; ArrayPool<T> blockArrayPool = _blockArrayPool;
@@ -90,6 +90,14 @@ namespace Recyclable.Collections
} }
int uninitializedBlocksCount = newArraySpan.Length; int uninitializedBlocksCount = newArraySpan.Length;
if (uninitializedBlocksCount == requiredBlockCount)
{
newArraySpan[0] = blockSize.RentArrayFromPool(blockArrayPool);
blockSize = newArraySpan[0].Length;
newArraySpan = newArraySpan[1..];
uninitializedBlocksCount--;
}
for (int i = 0; i < uninitializedBlocksCount; i++) for (int i = 0; i < uninitializedBlocksCount; i++)
{ {
newArraySpan[i] = blockSize.RentArrayFromPool(blockArrayPool); newArraySpan[i] = blockSize.RentArrayFromPool(blockArrayPool);
@@ -117,8 +125,8 @@ namespace Recyclable.Collections
{ {
long oldCapacity = _capacity; long oldCapacity = _capacity;
ref T[][] memory = ref _memoryBlocks; ref T[][] memory = ref _memoryBlocks;
long newCapacity; long newCapacity;
switch (oldCapacity > 0) switch (oldCapacity > 0)
{ {
case true: case true:
@@ -137,6 +145,12 @@ namespace Recyclable.Collections
int blockSize = _blockSize; int blockSize = _blockSize;
memory = SetNewLength(memory, blockSize, newCapacity); memory = SetNewLength(memory, blockSize, newCapacity);
if (oldCapacity == 0 && newCapacity > 0)
{
blockSize = memory[0].Length;
_blockSize = blockSize;
}
newCapacity = memory.Length * blockSize; newCapacity = memory.Length * blockSize;
_capacity = newCapacity; _capacity = newCapacity;
return newCapacity; return newCapacity;
@@ -144,28 +158,42 @@ namespace Recyclable.Collections
public RecyclableList(int blockSize = RecyclableDefaults.BlockSize, long? initialCapacity = default) public RecyclableList(int blockSize = RecyclableDefaults.BlockSize, long? initialCapacity = default)
{ {
_blockSize = blockSize; switch (initialCapacity > 0)
if (initialCapacity > 0)
{ {
_memoryBlocks = SetNewLength(_memoryBlocks, blockSize, initialCapacity.Value); case true:
_capacity = _memoryBlocks.Length * blockSize; _memoryBlocks = SetNewLength(_memoryBlocks, blockSize, initialCapacity.Value);
} if (_memoryBlocks.Length > 0)
else {
{ blockSize = _memoryBlocks[0].Length;
_memoryBlocks = _emptyBlockArray; }
_blockSize = blockSize;
_capacity = _memoryBlocks.Length * blockSize;
break;
case false:
_blockSize = blockSize;
_memoryBlocks = _emptyBlockArray;
break;
} }
} }
public RecyclableList(IEnumerable<T> source, int blockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default) public RecyclableList(IEnumerable<T> source, int blockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default)
{ {
_blockSize = blockSize;
if (expectedItemsCount > 0) if (expectedItemsCount > 0)
{ {
_memoryBlocks = SetNewLength(_memoryBlocks, blockSize, expectedItemsCount.Value); _memoryBlocks = SetNewLength(_memoryBlocks, blockSize, expectedItemsCount.Value);
if (_memoryBlocks.Length > 0)
{
blockSize = _memoryBlocks[0].Length;
}
_blockSize = blockSize;
_capacity = _memoryBlocks.Length * blockSize; _capacity = _memoryBlocks.Length * blockSize;
} }
else else
{ {
_blockSize = blockSize;
_memoryBlocks = _emptyBlockArray; _memoryBlocks = _emptyBlockArray;
} }