Optimize span-based stack AddRange
This commit is contained in:
1 parent
136c6408f3
commit
2de3736f94
1 file changed
+109
-8
@@ -79,10 +79,38 @@ namespace Recyclable.Collections
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal static void AddRange<T>(this RecyclableStack<T> stack, ReadOnlySpan<T> items)
|
||||
{
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
int count = items.Length;
|
||||
if (count == 0)
|
||||
{
|
||||
stack.Push(items[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureCapacity(stack, stack._count + count);
|
||||
|
||||
RecyclableArrayPoolChunk<T> chunk = stack._current;
|
||||
int index = chunk.Index;
|
||||
int chunkLength = chunk.Value.Length;
|
||||
int copied = 0;
|
||||
|
||||
while (copied < 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);
|
||||
items.Slice(copied, toCopy).CopyTo(new Span<T>(chunk.Value, index, toCopy));
|
||||
copied += toCopy;
|
||||
index += toCopy;
|
||||
}
|
||||
|
||||
chunk.Index = index;
|
||||
stack._count += count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -94,10 +122,39 @@ namespace Recyclable.Collections
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
internal static void AddRange<T>(this RecyclableStack<T> stack, in Array items)
|
||||
{
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
int count = items.Length;
|
||||
if (count == 0)
|
||||
{
|
||||
stack.Push((T)items.GetValue(i)!);
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureCapacity(stack, stack._count + count);
|
||||
|
||||
RecyclableArrayPoolChunk<T> chunk = stack._current;
|
||||
int index = chunk.Index;
|
||||
int chunkLength = chunk.Value.Length;
|
||||
int copied = 0;
|
||||
int lower = items.GetLowerBound(0);
|
||||
|
||||
while (copied < 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(items, lower + copied, chunk.Value, index, toCopy);
|
||||
copied += toCopy;
|
||||
index += toCopy;
|
||||
}
|
||||
|
||||
chunk.Index = index;
|
||||
stack._count += count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -118,11 +175,33 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(buffer, 0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
EnsureCapacity(stack, stack._count + count);
|
||||
|
||||
RecyclableArrayPoolChunk<T> chunk = stack._current;
|
||||
int index = chunk.Index;
|
||||
int chunkLength = chunk.Value.Length;
|
||||
int copied = 0;
|
||||
|
||||
while (copied < count)
|
||||
{
|
||||
stack.Push(buffer[i]);
|
||||
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(buffer, copied, chunk.Value, index, toCopy);
|
||||
copied += toCopy;
|
||||
index += toCopy;
|
||||
}
|
||||
|
||||
chunk.Index = index;
|
||||
stack._count += count;
|
||||
|
||||
if (count >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
RecyclableArrayPool<T>.ReturnShared(buffer, RecyclableStack<T>._needsClearing);
|
||||
@@ -144,11 +223,33 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(buffer, 0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
EnsureCapacity(stack, stack._count + count);
|
||||
|
||||
RecyclableArrayPoolChunk<T> chunk = stack._current;
|
||||
int index = chunk.Index;
|
||||
int chunkLength = chunk.Value.Length;
|
||||
int copied = 0;
|
||||
|
||||
while (copied < count)
|
||||
{
|
||||
stack.Push(buffer[i]);
|
||||
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(buffer, copied, chunk.Value, index, toCopy);
|
||||
copied += toCopy;
|
||||
index += toCopy;
|
||||
}
|
||||
|
||||
chunk.Index = index;
|
||||
stack._count += count;
|
||||
|
||||
if (count >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
RecyclableArrayPool<T>.ReturnShared(buffer, RecyclableStack<T>._needsClearing);
|
||||
|
||||
Reference in new issue
Block a user