Local int vars converted to stackalloc'ed array for performance measures. Recyclable.Add benchmarks yield 0.42 - 0.45 vs List.Add

This commit is contained in:
mlemanczyk committed 2023-01-29 21:34:14 +01:00
1 parent 7f90fcc969
commit 85fcf69c75
1 file changed
+22 -15
+22 -15
View File
@@ -78,28 +78,35 @@ namespace Recyclable.Collections
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected static T[][] SetNewLength(in T[][]? source, int minBlockSize, in long newCapacity, ArrayPool<T[]> memoryBlocksPool, ArrayPool<T> blockArrayPool)
{
var sourceBlockCount = source?.Length ?? 0;
int requiredBlockCount = (int)(newCapacity / minBlockSize) + (newCapacity % minBlockSize > 0 ? 1 : 0);
const int sourceBlockCount = 0, requiredBlockCount = 1, uninitializedBlocksCount = 2, i = 3;
T[][] newMemoryBlocks = requiredBlockCount < RecyclableDefaults.MinPooledArrayLength
? new T[requiredBlockCount][]
: memoryBlocksPool.Rent(requiredBlockCount);
Span<int> localInts = stackalloc int[4]
{
source?.Length ?? 0, // sourceBlockCount
(int)(newCapacity / minBlockSize) + (newCapacity % minBlockSize > 0 ? 1 : 0), // requiredBlockCount
0, // uninitializedBlocksCount
0, // i
};
T[][] newMemoryBlocks = localInts[requiredBlockCount] < RecyclableDefaults.MinPooledArrayLength
? new T[localInts[requiredBlockCount]][]
: memoryBlocksPool.Rent(localInts[requiredBlockCount]);
var newMemoryBlocksSpan = new Span<T[]>(newMemoryBlocks);
if (sourceBlockCount > 0)
if (localInts[sourceBlockCount] > 0)
{
var sourceSpan = new Span<T[]>(source);
sourceSpan.CopyTo(newMemoryBlocksSpan);
if (sourceSpan.Length >= RecyclableDefaults.MinPooledArrayLength)
if (localInts[sourceBlockCount] >= RecyclableDefaults.MinPooledArrayLength)
{
memoryBlocksPool.Return(source!);
}
newMemoryBlocksSpan = newMemoryBlocksSpan[sourceBlockCount..];
newMemoryBlocksSpan = newMemoryBlocksSpan[localInts[sourceBlockCount]..];
}
int uninitializedBlocksCount = newMemoryBlocksSpan.Length;
if (uninitializedBlocksCount == requiredBlockCount)
localInts[uninitializedBlocksCount] = newMemoryBlocksSpan.Length;
if (localInts[uninitializedBlocksCount] == localInts[requiredBlockCount])
{
if (minBlockSize >= RecyclableDefaults.MinPooledArrayLength)
{
@@ -112,21 +119,21 @@ namespace Recyclable.Collections
}
newMemoryBlocksSpan = newMemoryBlocksSpan[1..];
uninitializedBlocksCount--;
localInts[uninitializedBlocksCount]--;
}
if (minBlockSize >= RecyclableDefaults.MinPooledArrayLength)
{
for (int i = 0; i < uninitializedBlocksCount; i++)
for (localInts[i] = 0; localInts[i] < localInts[uninitializedBlocksCount]; localInts[i]++)
{
newMemoryBlocksSpan[i] = blockArrayPool.Rent(minBlockSize);
newMemoryBlocksSpan[localInts[i]] = blockArrayPool.Rent(minBlockSize);
}
}
else
{
for (int i = 0; i < uninitializedBlocksCount; i++)
for (localInts[i] = 0; localInts[i] < localInts[uninitializedBlocksCount]; localInts[i]++)
{
newMemoryBlocksSpan[i] = new T[minBlockSize];
newMemoryBlocksSpan[localInts[i]] = new T[minBlockSize];
}
}