RecyclableList.Resize & .Clear performance improvements.

This commit is contained in:
mlemanczyk committed 2023-04-18 00:20:07 +02:00
1 parent e5c0b2a231
commit 5ac21f5d18
1 file changed
+23 -14
+23 -14
View File
@@ -264,12 +264,12 @@ namespace Recyclable.Collections
int sourceBlockCount = list._reservedBlockCount; int sourceBlockCount = list._reservedBlockCount;
int requiredBlockCount = checked((int)(newCapacity >> minBlockSizePow2Shift) + ((newCapacity & (minBlockSize - 1)) > 0 ? 1 : 0)); int requiredBlockCount = checked((int)(newCapacity >> minBlockSizePow2Shift) + ((newCapacity & (minBlockSize - 1)) > 0 ? 1 : 0));
int blockIndex; int blockIndex;
Span<T[]> memoryBlocksSpan;
T[][] newMemoryBlocks;
if (requiredBlockCount > (list._memoryBlocks?.Length ?? 0)) if (requiredBlockCount > (list._memoryBlocks?.Length ?? 0))
{ {
// Allocate new memory block for all arrays // Allocate new memory block for all arrays
T[][] newMemoryBlocks = requiredBlockCount >= RecyclableDefaults.MinPooledArrayLength ? list._memoryBlocksPool.Rent(requiredBlockCount) : new T[requiredBlockCount][]; newMemoryBlocks = requiredBlockCount >= RecyclableDefaults.MinPooledArrayLength ? list._memoryBlocksPool.Rent(requiredBlockCount) : new T[requiredBlockCount][];
// Copy arrays from the old memory block for all arrays // Copy arrays from the old memory block for all arrays
if (sourceBlockCount > 0) if (sourceBlockCount > 0)
@@ -284,11 +284,14 @@ namespace Recyclable.Collections
list._memoryBlocks = newMemoryBlocks; list._memoryBlocks = newMemoryBlocks;
} }
else
{
newMemoryBlocks = list._memoryBlocks!;
}
// Allocate arrays for any new blocks // Allocate arrays for any new blocks
if (requiredBlockCount > sourceBlockCount) if (requiredBlockCount > sourceBlockCount)
{ {
memoryBlocksSpan = new(list._memoryBlocks!, sourceBlockCount, requiredBlockCount - sourceBlockCount);
if (minBlockSize >= RecyclableDefaults.MinPooledArrayLength) if (minBlockSize >= RecyclableDefaults.MinPooledArrayLength)
{ {
if (sourceBlockCount == 0) if (sourceBlockCount == 0)
@@ -296,11 +299,11 @@ namespace Recyclable.Collections
minBlockSize = GetEstimatedBlockSize(minBlockSize, blockArrayPool); minBlockSize = GetEstimatedBlockSize(minBlockSize, blockArrayPool);
} }
blockIndex = 0; blockIndex = sourceBlockCount;
do do
{ {
memoryBlocksSpan[blockIndex] = blockArrayPool.Rent(minBlockSize); newMemoryBlocks[blockIndex] = blockArrayPool.Rent(minBlockSize);
if (blockIndex + 1 < memoryBlocksSpan.Length) if (blockIndex + 1 < requiredBlockCount)
{ {
blockIndex++; blockIndex++;
} }
@@ -312,11 +315,11 @@ namespace Recyclable.Collections
} }
else else
{ {
blockIndex = 0; blockIndex = sourceBlockCount;
do do
{ {
memoryBlocksSpan[blockIndex] = new T[minBlockSize]; newMemoryBlocks[blockIndex] = new T[minBlockSize];
if (blockIndex + 1 < memoryBlocksSpan.Length) if (blockIndex + 1 < requiredBlockCount)
{ {
blockIndex++; blockIndex++;
} }
@@ -759,18 +762,24 @@ namespace Recyclable.Collections
public void Clear() public void Clear()
{ {
if (_longCount == 0)
{
return;
}
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength) if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
{ {
Span<T[]> memoryBlocksSpan = new(_memoryBlocks, 0, _reservedBlockCount); T[][] memoryBlocks = _memoryBlocks;
int memoryBlocksCount = memoryBlocksSpan.Length; int memoryBlocksCount = _reservedBlockCount;
ArrayPool<T> blockArrayPool = _blockArrayPool; ArrayPool<T> blockArrayPool = _blockArrayPool;
for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++) int toRemoveIdx = 0;
while (toRemoveIdx < memoryBlocksCount)
{ {
blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx], NeedsClearing); blockArrayPool.Return(memoryBlocks[toRemoveIdx++], NeedsClearing);
memoryBlocksSpan[toRemoveIdx] = _emptyBlockArray;
} }
} }
Array.Fill(_memoryBlocks, _emptyBlockArray, 0, _reservedBlockCount);
_capacity = 0; _capacity = 0;
_reservedBlockCount = 0; _reservedBlockCount = 0;
_nextItemBlockIndex = 0; _nextItemBlockIndex = 0;