Fix stack AddRange capacity growth

This commit is contained in:
Marek Lemańczyk committed 2025-07-17 00:21:20 +02:00
1 parent 1aedfb2cbc
commit 136c6408f3
1 file changed
+18 -61
@@ -168,29 +168,10 @@ namespace Recyclable.Collections
RecyclableArrayPoolChunk<T> chunk = stack._current; RecyclableArrayPoolChunk<T> chunk = stack._current;
int index = chunk.Index; int index = chunk.Index;
int chunkLength = chunk.Value.Length;
int copied = 0;
T[] source = items._memoryBlock; Array.Copy(items._memoryBlock, 0, chunk.Value, index, count);
while (copied < count) chunk.Index = index + count;
{
if (index == chunkLength)
{
chunk.Index = index;
Grow(stack);
chunk = stack._current;
index = chunk.Index;
chunkLength = chunk.Value.Length;
}
int toCopy = Math.Min(chunkLength - index, count - copied);
Array.Copy(source, copied, chunk.Value, index, toCopy);
copied += toCopy;
index += toCopy;
}
chunk.Index = index;
stack._count += count; stack._count += count;
} }
@@ -260,16 +241,23 @@ namespace Recyclable.Collections
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void EnsureCapacity<T>(RecyclableStack<T> stack, long requiredCapacity) private static void EnsureCapacity<T>(RecyclableStack<T> stack, long requiredCapacity)
{ {
if (stack._capacity >= requiredCapacity) long needed = requiredCapacity - stack._count;
if (needed <= 0)
{ {
return; return;
} }
long newCapacity = (long)Math.Min( if (stack._current.Value.Length - stack._current.Index >= needed)
BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity), {
(ulong)RecyclableDefaults.MaxPooledBlockSize); if (stack._capacity < requiredCapacity)
{
stack._capacity = requiredCapacity;
}
Grow(stack, newCapacity - stack._capacity); return;
}
Grow(stack, needed);
} }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
@@ -289,50 +277,19 @@ namespace Recyclable.Collections
RecyclableArrayPoolChunk<T> chunk = stack._current; RecyclableArrayPoolChunk<T> chunk = stack._current;
int index = chunk.Index; int index = chunk.Index;
int chunkLength = chunk.Value.Length;
for (int blockIndex = 0; blockIndex < fullBlocks; blockIndex++) for (int blockIndex = 0; blockIndex < fullBlocks; blockIndex++)
{ {
T[] block = items._memoryBlocks[blockIndex]; T[] block = items._memoryBlocks[blockIndex];
int sourceIndex = 0; Array.Copy(block, 0, chunk.Value, index, blockSize);
while (sourceIndex < blockSize) index += blockSize;
{
if (index == chunkLength)
{
chunk.Index = index;
Grow(stack);
chunk = stack._current;
index = chunk.Index;
chunkLength = chunk.Value.Length;
}
int toCopy = Math.Min(chunkLength - index, blockSize - sourceIndex);
Array.Copy(block, sourceIndex, chunk.Value, index, toCopy);
sourceIndex += toCopy;
index += toCopy;
}
} }
if (lastBlockLength > 0) if (lastBlockLength > 0)
{ {
T[] block = items._memoryBlocks[fullBlocks]; T[] block = items._memoryBlocks[fullBlocks];
int sourceIndex = 0; Array.Copy(block, 0, chunk.Value, index, lastBlockLength);
while (sourceIndex < lastBlockLength) index += lastBlockLength;
{
if (index == chunkLength)
{
chunk.Index = index;
Grow(stack);
chunk = stack._current;
index = chunk.Index;
chunkLength = chunk.Value.Length;
}
int toCopy = Math.Min(chunkLength - index, lastBlockLength - sourceIndex);
Array.Copy(block, sourceIndex, chunk.Value, index, toCopy);
sourceIndex += toCopy;
index += toCopy;
}
} }
chunk.Index = index; chunk.Index = index;