Added rented array clearing if T is a reference type, as discussed in https://github.com/dotnet/runtime/issues/25378.

This commit is contained in:
mlemanczyk committed 2023-03-22 00:04:25 +01:00
1 parent d4af246a3a
commit 0f7237e3f0
4 files changed
+18 -11

No files matched your search

@@ -9,6 +9,8 @@ namespace Recyclable.Collections
private static readonly ArrayPool<T> _arrayPool = ArrayPool<T>.Create(); private static readonly ArrayPool<T> _arrayPool = ArrayPool<T>.Create();
private static readonly IEqualityComparer<T> _equalityComparer = EqualityComparer<T>.Default; private static readonly IEqualityComparer<T> _equalityComparer = EqualityComparer<T>.Default;
protected static readonly bool NeedsClearing = !typeof(T).IsValueType;
protected T[] _memoryBlock; protected T[] _memoryBlock;
private static void ThrowArgumentOutOfRangeException(in string message) private static void ThrowArgumentOutOfRangeException(in string message)
@@ -32,7 +34,7 @@ namespace Recyclable.Collections
sourceSpan.CopyTo(newArraySpan); sourceSpan.CopyTo(newArraySpan);
if (sourceLength >= RecyclableDefaults.MinPooledArrayLength) if (sourceLength >= RecyclableDefaults.MinPooledArrayLength)
{ {
arrayPool.Return(source!); arrayPool.Return(source!, NeedsClearing);
} }
} }
@@ -464,7 +466,7 @@ namespace Recyclable.Collections
{ {
Clear(); Clear();
_capacity = 0; _capacity = 0;
_memoryBlock.ReturnToPool(_arrayPool); _memoryBlock.ReturnToPool(_arrayPool, NeedsClearing);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
} }
+9 -6
View File
@@ -18,6 +18,9 @@ namespace Recyclable.Collections
private int _blockSize; private int _blockSize;
private int _lastBlockIndex; private int _lastBlockIndex;
private int _nextItemIndex; private int _nextItemIndex;
protected static readonly bool NeedsClearing = !typeof(T).IsValueType;
protected ArrayPool<T[]> _memoryBlocksPool; protected ArrayPool<T[]> _memoryBlocksPool;
protected ArrayPool<T> _blockArrayPool; protected ArrayPool<T> _blockArrayPool;
protected T[][] _memoryBlocks; protected T[][] _memoryBlocks;
@@ -70,7 +73,7 @@ namespace Recyclable.Collections
T[][] memoryBlocks = list._memoryBlocks; T[][] memoryBlocks = list._memoryBlocks;
if (blockSize >= RecyclableDefaults.MinPooledArrayLength) if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
{ {
blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1]); blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1], NeedsClearing);
} }
list._capacity -= blockSize; list._capacity -= blockSize;
@@ -247,7 +250,7 @@ namespace Recyclable.Collections
sourceSpan.CopyTo(newMemoryBlocksSpan); sourceSpan.CopyTo(newMemoryBlocksSpan);
if (localInts[sourceBlockCount] >= RecyclableDefaults.MinPooledArrayLength) if (localInts[sourceBlockCount] >= RecyclableDefaults.MinPooledArrayLength)
{ {
memoryBlocksPool.Return(source!); memoryBlocksPool.Return(source!, NeedsClearing);
} }
newMemoryBlocksSpan = newMemoryBlocksSpan[localInts[sourceBlockCount]..]; newMemoryBlocksSpan = newMemoryBlocksSpan[localInts[sourceBlockCount]..];
@@ -648,7 +651,7 @@ namespace Recyclable.Collections
{ {
if (items.Count >= RecyclableDefaults.MinPooledArrayLength) if (items.Count >= RecyclableDefaults.MinPooledArrayLength)
{ {
_blockArrayPool.Return(itemsBuffer); _blockArrayPool.Return(itemsBuffer, NeedsClearing);
} }
} }
} }
@@ -703,7 +706,7 @@ namespace Recyclable.Collections
ArrayPool<T> blockArrayPool = _blockArrayPool; ArrayPool<T> blockArrayPool = _blockArrayPool;
for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++) for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
{ {
blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx]); blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx], NeedsClearing);
} }
} }
@@ -777,7 +780,7 @@ namespace Recyclable.Collections
} }
else else
{ {
_blockArrayPool.Return(_memoryBlocks[index]); _blockArrayPool.Return(_memoryBlocks[index], NeedsClearing);
} }
_capacity -= _blockSize; _capacity -= _blockSize;
@@ -810,7 +813,7 @@ namespace Recyclable.Collections
Clear(); Clear();
if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength) if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength)
{ {
_memoryBlocksPool.Return(_memoryBlocks); _memoryBlocksPool.Return(_memoryBlocks, NeedsClearing);
} }
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
@@ -155,11 +155,11 @@ namespace Recyclable.Collections
: new T[minSize]; : new T[minSize];
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ReturnToPool<T>(this T[] array, ArrayPool<T> arrayPool) public static void ReturnToPool<T>(this T[] array, ArrayPool<T> arrayPool, bool needsClearing)
{ {
if (array.LongLength is > _minPooledArraySize and <= int.MaxValue) if (array.LongLength is > _minPooledArraySize and <= int.MaxValue)
{ {
arrayPool.Return(array); arrayPool.Return(array, needsClearing);
} }
} }
+3 -1
View File
@@ -45,6 +45,8 @@ namespace Recyclable.Collections
return false; return false;
} }
protected static readonly bool NeedsClearing = !typeof(T).IsValueType;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
protected static long GetAbsoluteIndex(long index, long removedCount) => index + removedCount; protected static long GetAbsoluteIndex(long index, long removedCount) => index + removedCount;
@@ -181,7 +183,7 @@ namespace Recyclable.Collections
{ {
try try
{ {
Memory[index].ReturnToPool(_arrayPool); Memory[index].ReturnToPool(_arrayPool, NeedsClearing);
Memory.RemoveAt(index); Memory.RemoveAt(index);
} }
finally finally