Skip to content

Commit

Permalink
Improve performance of LargeArrayBuilder.CopyTo()
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmada committed Jul 15, 2020
1 parent 5a050bf commit d1a8b93
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 37 deletions.
2 changes: 1 addition & 1 deletion NetFabric.Hyperlinq/Conversion/ToList/ToList.Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public static partial class ArrayExtensions

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static List<TSource> ToList<TSource>(this TSource[] source)
=> ArrayExtensions.ToList(source.AsMemory()); // Memory<> uses ICollection<>
=> ArrayExtensions.ToList((ReadOnlyMemory<TSource>)source.AsMemory()); // Memory<> uses ICollection<>

}
}
55 changes: 19 additions & 36 deletions NetFabric.Hyperlinq/Utils/ArrayBuilder/LargeArrayBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,53 +94,36 @@ public void Add([AllowNull] T item)
{
Debug.Assert(arrayIndex <= array.Length);

var count = Count;
for (var index = 0; count > 0; index++)
for (var bufferIndex = 0; bufferIndex < buffers.Count; bufferIndex++)
{
// Find the buffer we're copying from.
var buffer = GetBuffer(index);
var buffer = buffers[bufferIndex];
var length = buffer.Length;
Array.Copy(buffer, 0, array, arrayIndex, length);

// Copy until we satisfy count, or we reach the end of the buffer.
var toCopy = Math.Min(count, buffer.Length);
Array.Copy(buffer, 0, array, arrayIndex, toCopy);

// Increment variables to that position.
count -= toCopy;
arrayIndex += toCopy;
arrayIndex += length;
}
if (arrayIndex < Count)
{
Array.Copy(current, 0, array, arrayIndex, Count - arrayIndex);
}
}

public readonly void CopyTo(Span<T> span)
{
var count = Count;
var arrayIndex = 0;
for (var index = 0; count > 0; index++)
for (var bufferIndex = 0; bufferIndex < buffers.Count; bufferIndex++)
{
// Find the buffer we're copying from.
var buffer = GetBuffer(index);

// Copy until we satisfy count, or we reach the end of the buffer.
var toCopy = Math.Min(count, buffer.Length);
buffer.AsSpan().Slice(0, toCopy).CopyTo(span.Slice(arrayIndex, toCopy));
var buffer = buffers[bufferIndex];
var length = buffer.Length;
buffer.AsSpan().CopyTo(span.Slice(arrayIndex, length));

// Increment variables to that position.
count -= toCopy;
arrayIndex += toCopy;
arrayIndex += length;
}
if (arrayIndex < Count)
{
var length = Count - arrayIndex;
current.AsSpan().Slice(0, length).CopyTo(span.Slice(arrayIndex, length));
}
}

/// <summary>
/// Retrieves the buffer at the specified index.
/// </summary>
/// <param name="index">The index of the buffer.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly T[] GetBuffer(int index)
{
Debug.Assert(index >= 0 && index < buffers.Count + 1);

return index < buffers.Count
? buffers[index]!
: current;
}

/// <summary>
Expand Down

0 comments on commit d1a8b93

Please sign in to comment.