From 71544f8a47aeb0f6c3798241302e83cb94d08f43 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sun, 29 Jan 2023 18:05:27 +0100 Subject: [PATCH] Finished RecyclableList implementation of array pool overriding. --- Recyclable.Collections/RecyclableList.cs | 45 ++++++++++++++---------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index 9566f90..68d0135 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -6,8 +6,8 @@ namespace Recyclable.Collections { public class RecyclableList : IDisposable, IList { - private static readonly ArrayPool _arrayPool = ArrayPool.Create(); - private static readonly ArrayPool _blockArrayPool = ArrayPool.Create(); + private static readonly ArrayPool _defaultMemoryBlocksPool = ArrayPool.Create(); + private static readonly ArrayPool _defaultBlockArrayPool = ArrayPool.Create(); private static readonly T[][] _emptyMemoryBlocksArray = new T[0][]; private static readonly T[] _emptyBlockArray = new T[0]; private static readonly IEqualityComparer _equalityComparer = EqualityComparer.Default; @@ -15,6 +15,8 @@ namespace Recyclable.Collections private int _blockSize; private int _lastBlockIndex; private int _lastItemIndex; + protected ArrayPool _memoryBlocksPool; + protected ArrayPool _blockArrayPool; protected T[][] _memoryBlocks; private long _capacity; @@ -36,7 +38,7 @@ namespace Recyclable.Collections public bool IsReadOnly { get; } = false; public int BlockCount => _memoryBlocks.Length; - private static void RemoveAt(RecyclableList list, long index) + private static void RemoveAt(RecyclableList list, long index, ArrayPool blockArrayPool) { long oldCountMinus1 = list._longCount - 1; if (index != oldCountMinus1) @@ -61,7 +63,7 @@ namespace Recyclable.Collections T[][] memoryBlocks = list._memoryBlocks; if (blockSize >= RecyclableDefaults.MinPooledArrayLength) { - _blockArrayPool.Return(memoryBlocks[list.BlockCount - 1]); + blockArrayPool.Return(memoryBlocks[list.BlockCount - 1]); } list._capacity -= blockSize; @@ -74,15 +76,14 @@ namespace Recyclable.Collections } [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected static T[][] SetNewLength(in T[][]? source, int minBlockSize, in long newCapacity) + protected static T[][] SetNewLength(in T[][]? source, int minBlockSize, in long newCapacity, ArrayPool memoryBlocksPool, ArrayPool blockArrayPool) { - ArrayPool arrayPool = _arrayPool; var sourceBlockCount = source?.Length ?? 0; int requiredBlockCount = (int)(newCapacity / minBlockSize) + (newCapacity % minBlockSize > 0 ? 1 : 0); T[][] newMemoryBlocks = requiredBlockCount < RecyclableDefaults.MinPooledArrayLength ? new T[requiredBlockCount][] - : arrayPool.Rent(requiredBlockCount); + : memoryBlocksPool.Rent(requiredBlockCount); var newMemoryBlocksSpan = new Span(newMemoryBlocks); if (sourceBlockCount > 0) @@ -91,13 +92,12 @@ namespace Recyclable.Collections sourceSpan.CopyTo(newMemoryBlocksSpan); if (sourceSpan.Length >= RecyclableDefaults.MinPooledArrayLength) { - arrayPool.Return(source!); + memoryBlocksPool.Return(source!); } newMemoryBlocksSpan = newMemoryBlocksSpan[sourceBlockCount..]; } - ArrayPool blockArrayPool = _blockArrayPool; int uninitializedBlocksCount = newMemoryBlocksSpan.Length; if (uninitializedBlocksCount == requiredBlockCount) { @@ -151,7 +151,7 @@ namespace Recyclable.Collections newCapacity = requestedCapacity; } - memory = SetNewLength(memory, _blockSize, newCapacity); + memory = SetNewLength(memory, _blockSize, newCapacity, _memoryBlocksPool, _blockArrayPool); if (newCapacity > 0 && _capacity == 0) { _blockSize = memory[0].Length; @@ -163,11 +163,16 @@ namespace Recyclable.Collections return newCapacity; } - public RecyclableList(int minBlockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default) + public RecyclableList(int minBlockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default, ArrayPool? memoryBlocksPool = default, ArrayPool? blockArrayPool = default) { + memoryBlocksPool ??= _defaultMemoryBlocksPool; + blockArrayPool ??= _defaultBlockArrayPool; + _memoryBlocksPool = memoryBlocksPool; + _blockArrayPool = blockArrayPool; + if (expectedItemsCount > 0) { - _memoryBlocks = SetNewLength(_memoryBlocks, minBlockSize, expectedItemsCount.Value); + _memoryBlocks = SetNewLength(_memoryBlocks, minBlockSize, expectedItemsCount.Value, memoryBlocksPool, blockArrayPool); if (_memoryBlocks.Length > 0) { minBlockSize = _memoryBlocks[0].Length; @@ -183,11 +188,15 @@ namespace Recyclable.Collections } } - public RecyclableList(IEnumerable source, int minBlockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default) + public RecyclableList(IEnumerable source, int minBlockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default, ArrayPool? memoryBlocksPool = default, ArrayPool? blockArrayPool = default) { + memoryBlocksPool ??= _defaultMemoryBlocksPool; + blockArrayPool ??= _defaultBlockArrayPool; + _memoryBlocksPool = memoryBlocksPool; + _blockArrayPool = blockArrayPool; if (expectedItemsCount > 0) { - _memoryBlocks = SetNewLength(_memoryBlocks, minBlockSize, expectedItemsCount.Value); + _memoryBlocks = SetNewLength(_memoryBlocks, minBlockSize, expectedItemsCount.Value, memoryBlocksPool, blockArrayPool); if (_memoryBlocks.Length > 0) { minBlockSize = _memoryBlocks[0].Length; @@ -379,7 +388,7 @@ namespace Recyclable.Collections long oldLongCount = _longCount; int blockSize = _blockSize; int targetItemIdx = (int)(oldLongCount % blockSize); - int targetBlockIdx = targetItemIdx / blockSize + (targetItemIdx > 0 ? 1 : 0); + int targetBlockIdx = (targetItemIdx / blockSize) + (targetItemIdx > 0 ? 1 : 0); Span memoryBlocksSpan; Span blockArraySpan; @@ -520,8 +529,8 @@ namespace Recyclable.Collections } } - public void RemoveAt(int index) => RemoveAt(this, index); - public void RemoveAt(long index) => RemoveAt(this, index); + public void RemoveAt(int index) => RemoveAt(this, index, _blockArrayPool); + public void RemoveAt(long index) => RemoveAt(this, index, _blockArrayPool); IEnumerator IEnumerable.GetEnumerator() => _memoryBlocks.Enumerate(_blockSize, LongCount).GetEnumerator(); @@ -533,7 +542,7 @@ namespace Recyclable.Collections _capacity = 0; if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength) { - _arrayPool.Return(_memoryBlocks); + _memoryBlocksPool.Return(_memoryBlocks); } GC.SuppressFinalize(this);