RecyclableList.Clear, .RemoveAt, .RemoveBlock, .SetNewLength, Dispose performance improvements.
This commit is contained in:
1 parent
032908bc7d
commit
f9b2d82629
1 file changed
+82
-23
@@ -8,7 +8,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 ArrayPool<T> _blockArrayPool = ArrayPool<T>.Create();
|
private static readonly ArrayPool<T> _blockArrayPool = ArrayPool<T>.Create();
|
||||||
private static readonly T[][] _emptyBlockArray = new T[0][];
|
private static readonly T[][] _emptyMemoryBlocksArray = 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 int _blockSize;
|
private int _blockSize;
|
||||||
@@ -60,7 +61,11 @@ namespace Recyclable.Collections
|
|||||||
if ((list._capacity * blockSize) - oldCountMinus1 == blockSize)
|
if ((list._capacity * blockSize) - oldCountMinus1 == blockSize)
|
||||||
{
|
{
|
||||||
T[][] memoryBlocks = list._memoryBlocks;
|
T[][] memoryBlocks = list._memoryBlocks;
|
||||||
memoryBlocks[list.BlockCount - 1].ReturnToPool(_blockArrayPool);
|
if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
_blockArrayPool.Return(memoryBlocks[list.BlockCount - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
list._capacity -= blockSize;
|
list._capacity -= blockSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +88,10 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
Span<T[]> newArraySpan;
|
Span<T[]> newArraySpan;
|
||||||
T[][] newMemoryBlocks = requiredBlockCount.RentArrayFromPool(arrayPool);
|
T[][] newMemoryBlocks = requiredBlockCount > RecyclableDefaults.MinPooledArrayLength
|
||||||
|
? arrayPool.Rent(requiredBlockCount)
|
||||||
|
: new T[requiredBlockCount][];
|
||||||
|
|
||||||
switch (requiredBlockCount >= sourceBlockCount)
|
switch (requiredBlockCount >= sourceBlockCount)
|
||||||
{
|
{
|
||||||
case true:
|
case true:
|
||||||
@@ -93,7 +101,11 @@ namespace Recyclable.Collections
|
|||||||
Memory<T[]> sourceMemory = new(source);
|
Memory<T[]> sourceMemory = new(source);
|
||||||
Memory<T[]> newArrayMemory = new(newMemoryBlocks);
|
Memory<T[]> newArrayMemory = new(newMemoryBlocks);
|
||||||
sourceMemory.CopyTo(newArrayMemory);
|
sourceMemory.CopyTo(newArrayMemory);
|
||||||
source!.ReturnToPool(arrayPool);
|
if (sourceMemory.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
arrayPool.Return(source!);
|
||||||
|
}
|
||||||
|
|
||||||
newArraySpan = new Span<T[]>(newMemoryBlocks)[sourceBlockCount..];
|
newArraySpan = new Span<T[]>(newMemoryBlocks)[sourceBlockCount..];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -105,15 +117,39 @@ namespace Recyclable.Collections
|
|||||||
int uninitializedBlocksCount = newArraySpan.Length;
|
int uninitializedBlocksCount = newArraySpan.Length;
|
||||||
if (uninitializedBlocksCount == requiredBlockCount)
|
if (uninitializedBlocksCount == requiredBlockCount)
|
||||||
{
|
{
|
||||||
newArraySpan[0] = blockSize.RentArrayFromPool(blockArrayPool);
|
switch (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
blockSize = newArraySpan[0].Length;
|
{
|
||||||
|
case true:
|
||||||
|
newArraySpan[0] = blockArrayPool.Rent(blockSize);
|
||||||
|
blockSize = newArraySpan[0].Length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case false:
|
||||||
|
newArraySpan[0] = new T[blockSize];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
newArraySpan = newArraySpan[1..];
|
newArraySpan = newArraySpan[1..];
|
||||||
uninitializedBlocksCount--;
|
uninitializedBlocksCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < uninitializedBlocksCount; i++)
|
switch (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
newArraySpan[i] = blockSize.RentArrayFromPool(blockArrayPool);
|
case true:
|
||||||
|
for (int i = 0; i < uninitializedBlocksCount; i++)
|
||||||
|
{
|
||||||
|
newArraySpan[i] = blockArrayPool.Rent(blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case false:
|
||||||
|
for (int i = 0; i < uninitializedBlocksCount; i++)
|
||||||
|
{
|
||||||
|
newArraySpan[i] = new T[blockSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newMemoryBlocks;
|
return newMemoryBlocks;
|
||||||
@@ -124,12 +160,19 @@ namespace Recyclable.Collections
|
|||||||
sourceSpan.CopyTo(newArraySpan);
|
sourceSpan.CopyTo(newArraySpan);
|
||||||
sourceSpan = new Span<T[]>(source)[newArraySpan.Length..];
|
sourceSpan = new Span<T[]>(source)[newArraySpan.Length..];
|
||||||
int sourceLength = sourceSpan.Length;
|
int sourceLength = sourceSpan.Length;
|
||||||
for (int i = 0; i < sourceLength; i++)
|
if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
sourceSpan[i].ReturnToPool(blockArrayPool);
|
for (int i = 0; i < sourceLength; i++)
|
||||||
|
{
|
||||||
|
blockArrayPool.Return(sourceSpan[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceLength >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
arrayPool.Return(source!);
|
||||||
}
|
}
|
||||||
|
|
||||||
source!.ReturnToPool(arrayPool);
|
|
||||||
return newMemoryBlocks;
|
return newMemoryBlocks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,7 +229,7 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
case false:
|
case false:
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_memoryBlocks = _emptyBlockArray;
|
_memoryBlocks = _emptyMemoryBlocksArray;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +251,7 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
case false:
|
case false:
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_memoryBlocks = _emptyBlockArray;
|
_memoryBlocks = _emptyMemoryBlocksArray;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,12 +521,15 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
Span<T[]> memoryBlocksSpan = new(_memoryBlocks);
|
|
||||||
int memoryBlocksCount = memoryBlocksSpan.Length;
|
|
||||||
for (var toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
|
|
||||||
{
|
{
|
||||||
memoryBlocksSpan[toRemoveIdx].ReturnToPool(blockArrayPool);
|
Span<T[]> memoryBlocksSpan = new(_memoryBlocks);
|
||||||
|
int memoryBlocksCount = memoryBlocksSpan.Length;
|
||||||
|
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
||||||
|
for (var toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
|
||||||
|
{
|
||||||
|
blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_capacity = 0;
|
_capacity = 0;
|
||||||
@@ -504,14 +550,23 @@ namespace Recyclable.Collections
|
|||||||
public bool Remove(T item) => throw new NotSupportedException();
|
public bool Remove(T item) => throw new NotSupportedException();
|
||||||
public void RemoveBlock(int index)
|
public void RemoveBlock(int index)
|
||||||
{
|
{
|
||||||
_memoryBlocks[index].ReturnToPool(_blockArrayPool);
|
switch (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
case true:
|
||||||
|
_blockArrayPool.Return(_memoryBlocks[index]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case false:
|
||||||
|
_memoryBlocks[index] = _emptyBlockArray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
_capacity -= _blockSize;
|
_capacity -= _blockSize;
|
||||||
int lastBlockIndex = _lastBlockIndex;
|
if (_lastBlockIndex == index)
|
||||||
if (lastBlockIndex == index)
|
|
||||||
{
|
{
|
||||||
_lastItemIndex = 0;
|
_lastItemIndex = 0;
|
||||||
}
|
}
|
||||||
else if (lastBlockIndex > index)
|
else if (_lastBlockIndex > index)
|
||||||
{
|
{
|
||||||
_lastBlockIndex--;
|
_lastBlockIndex--;
|
||||||
}
|
}
|
||||||
@@ -528,7 +583,11 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
_capacity = 0;
|
_capacity = 0;
|
||||||
_memoryBlocks.ReturnToPool(_arrayPool);
|
if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
_arrayPool.Return(_memoryBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user