RecyclableList performance optimizations.
This commit is contained in:
1 parent
30dfd97336
commit
f45b6aac98
1 file changed
+40
-12
@@ -11,7 +11,7 @@ namespace Recyclable.Collections
|
|||||||
private static readonly T[][] _emptyBlockArray = 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 readonly int _blockSize;
|
private int _blockSize;
|
||||||
protected T[][] _memoryBlocks;
|
protected T[][] _memoryBlocks;
|
||||||
|
|
||||||
private long _capacity;
|
private long _capacity;
|
||||||
@@ -58,7 +58,7 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
protected static T[][] SetNewLength(in T[][]? source, in int blockSize, in long newCapacity)
|
protected static T[][] SetNewLength(in T[][]? source, int blockSize, in long newCapacity)
|
||||||
{
|
{
|
||||||
ArrayPool<T[]> arrayPool = _arrayPool;
|
ArrayPool<T[]> arrayPool = _arrayPool;
|
||||||
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
||||||
@@ -90,6 +90,14 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
int uninitializedBlocksCount = newArraySpan.Length;
|
int uninitializedBlocksCount = newArraySpan.Length;
|
||||||
|
if (uninitializedBlocksCount == requiredBlockCount)
|
||||||
|
{
|
||||||
|
newArraySpan[0] = blockSize.RentArrayFromPool(blockArrayPool);
|
||||||
|
blockSize = newArraySpan[0].Length;
|
||||||
|
newArraySpan = newArraySpan[1..];
|
||||||
|
uninitializedBlocksCount--;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < uninitializedBlocksCount; i++)
|
for (int i = 0; i < uninitializedBlocksCount; i++)
|
||||||
{
|
{
|
||||||
newArraySpan[i] = blockSize.RentArrayFromPool(blockArrayPool);
|
newArraySpan[i] = blockSize.RentArrayFromPool(blockArrayPool);
|
||||||
@@ -117,8 +125,8 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
long oldCapacity = _capacity;
|
long oldCapacity = _capacity;
|
||||||
ref T[][] memory = ref _memoryBlocks;
|
ref T[][] memory = ref _memoryBlocks;
|
||||||
|
|
||||||
long newCapacity;
|
long newCapacity;
|
||||||
|
|
||||||
switch (oldCapacity > 0)
|
switch (oldCapacity > 0)
|
||||||
{
|
{
|
||||||
case true:
|
case true:
|
||||||
@@ -137,6 +145,12 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
int blockSize = _blockSize;
|
int blockSize = _blockSize;
|
||||||
memory = SetNewLength(memory, blockSize, newCapacity);
|
memory = SetNewLength(memory, blockSize, newCapacity);
|
||||||
|
if (oldCapacity == 0 && newCapacity > 0)
|
||||||
|
{
|
||||||
|
blockSize = memory[0].Length;
|
||||||
|
_blockSize = blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
newCapacity = memory.Length * blockSize;
|
newCapacity = memory.Length * blockSize;
|
||||||
_capacity = newCapacity;
|
_capacity = newCapacity;
|
||||||
return newCapacity;
|
return newCapacity;
|
||||||
@@ -144,28 +158,42 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
public RecyclableList(int blockSize = RecyclableDefaults.BlockSize, long? initialCapacity = default)
|
public RecyclableList(int blockSize = RecyclableDefaults.BlockSize, long? initialCapacity = default)
|
||||||
{
|
{
|
||||||
_blockSize = blockSize;
|
switch (initialCapacity > 0)
|
||||||
if (initialCapacity > 0)
|
|
||||||
{
|
{
|
||||||
_memoryBlocks = SetNewLength(_memoryBlocks, blockSize, initialCapacity.Value);
|
case true:
|
||||||
_capacity = _memoryBlocks.Length * blockSize;
|
_memoryBlocks = SetNewLength(_memoryBlocks, blockSize, initialCapacity.Value);
|
||||||
}
|
if (_memoryBlocks.Length > 0)
|
||||||
else
|
{
|
||||||
{
|
blockSize = _memoryBlocks[0].Length;
|
||||||
_memoryBlocks = _emptyBlockArray;
|
}
|
||||||
|
|
||||||
|
_blockSize = blockSize;
|
||||||
|
_capacity = _memoryBlocks.Length * blockSize;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case false:
|
||||||
|
_blockSize = blockSize;
|
||||||
|
_memoryBlocks = _emptyBlockArray;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecyclableList(IEnumerable<T> source, int blockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default)
|
public RecyclableList(IEnumerable<T> source, int blockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default)
|
||||||
{
|
{
|
||||||
_blockSize = blockSize;
|
|
||||||
if (expectedItemsCount > 0)
|
if (expectedItemsCount > 0)
|
||||||
{
|
{
|
||||||
_memoryBlocks = SetNewLength(_memoryBlocks, blockSize, expectedItemsCount.Value);
|
_memoryBlocks = SetNewLength(_memoryBlocks, blockSize, expectedItemsCount.Value);
|
||||||
|
if (_memoryBlocks.Length > 0)
|
||||||
|
{
|
||||||
|
blockSize = _memoryBlocks[0].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
_blockSize = blockSize;
|
||||||
_capacity = _memoryBlocks.Length * blockSize;
|
_capacity = _memoryBlocks.Length * blockSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_blockSize = blockSize;
|
||||||
_memoryBlocks = _emptyBlockArray;
|
_memoryBlocks = _emptyBlockArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user