RecyclableList.AddRange(T[] items) performance improvements.

This commit is contained in:
Marek Lemańczyk committed 2023-03-11 15:51:52 +01:00
1 parent f76276c7a4
commit e7e670ae35
1 file changed
+10 -19
+10 -19
View File
@@ -8,6 +8,7 @@ namespace Recyclable.Collections
{ {
private const int ItemNotFoundIndex = -1; private const int ItemNotFoundIndex = -1;
private const int BatchSize = 8; private const int BatchSize = 8;
private static readonly ArrayPool<T[]> _defaultMemoryBlocksPool = ArrayPool<T[]>.Create(); private static readonly ArrayPool<T[]> _defaultMemoryBlocksPool = ArrayPool<T[]>.Create();
private static readonly ArrayPool<T> _defaultBlockArrayPool = ArrayPool<T>.Create(); private static readonly ArrayPool<T> _defaultBlockArrayPool = ArrayPool<T>.Create();
private static readonly T[][] _emptyMemoryBlocksArray = new T[0][]; private static readonly T[][] _emptyMemoryBlocksArray = new T[0][];
@@ -280,30 +281,20 @@ namespace Recyclable.Collections
_ = EnsureCapacity(targetCapacity); _ = EnsureCapacity(targetCapacity);
} }
int blockSize = _blockSize, targetBlockIndex = _lastBlockIndex, toCopy = 0; int blockSize = _blockSize, targetBlockIndex = _lastBlockIndex;
Span<T> itemsSpan = new(items); Span<T> itemsSpan = new(items);
Span<T[]> memoryBlocksSpan = new(_memoryBlocks); Span<T[]> memoryBlocksSpan = new(_memoryBlocks, 0, _memoryBlocks.Length);
Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], _nextItemIndex, blockSize - _nextItemIndex); Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], _nextItemIndex, blockSize - _nextItemIndex);
while (!itemsSpan.IsEmpty) while (targetBlockArraySpan.Length <= itemsSpan.Length)
{ {
if (targetBlockArraySpan.Length < itemsSpan.Length) itemsSpan[..targetBlockArraySpan.Length].CopyTo(targetBlockArraySpan);
{ itemsSpan = itemsSpan[targetBlockArraySpan.Length..];
toCopy = targetBlockArraySpan.Length; targetBlockIndex++;
itemsSpan[..toCopy].CopyTo(targetBlockArraySpan); targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], 0, blockSize);
targetBlockIndex++;
targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex]);
}
else
{
toCopy = itemsSpan.Length;
itemsSpan[..toCopy].CopyTo(targetBlockArraySpan);
targetBlockArraySpan = targetBlockArraySpan[..toCopy];
}
itemsSpan = itemsSpan[toCopy..];
} }
_nextItemIndex = toCopy; _nextItemIndex = itemsSpan.Length;
itemsSpan[..itemsSpan.Length].CopyTo(targetBlockArraySpan);
_longCount = targetCapacity; _longCount = targetCapacity;
_lastBlockIndex = targetBlockIndex; _lastBlockIndex = targetBlockIndex;
} }