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)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void AddRange<T>(this RecyclableStack<T> stack, ReadOnlySpan<T> items)
|
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)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
@@ -94,10 +122,39 @@ namespace Recyclable.Collections
|
|||||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void AddRange<T>(this RecyclableStack<T> stack, in Array items)
|
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)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
@@ -118,11 +175,33 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
items.CopyTo(buffer, 0);
|
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)
|
if (count >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
RecyclableArrayPool<T>.ReturnShared(buffer, RecyclableStack<T>._needsClearing);
|
RecyclableArrayPool<T>.ReturnShared(buffer, RecyclableStack<T>._needsClearing);
|
||||||
@@ -144,11 +223,33 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
items.CopyTo(buffer, 0);
|
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)
|
if (count >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
RecyclableArrayPool<T>.ReturnShared(buffer, RecyclableStack<T>._needsClearing);
|
RecyclableArrayPool<T>.ReturnShared(buffer, RecyclableStack<T>._needsClearing);
|
||||||
|
|||||||
Reference in new issue
Block a user