diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index 74721a5..d0b8e28 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -78,28 +78,35 @@ namespace Recyclable.Collections [MethodImpl(MethodImplOptions.AggressiveInlining)] protected static T[][] SetNewLength(in T[][]? source, int minBlockSize, in long newCapacity, ArrayPool memoryBlocksPool, ArrayPool 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 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(newMemoryBlocks); - if (sourceBlockCount > 0) + if (localInts[sourceBlockCount] > 0) { var sourceSpan = new Span(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]; } }