Reduce overhead of ReadOnlySequence<T>.CopyTo (dotnet/corefx#35819)
authorStephen Toub <stoub@microsoft.com>
Wed, 6 Mar 2019 19:10:46 +0000 (11:10 -0800)
committerGitHub <noreply@github.com>
Wed, 6 Mar 2019 19:10:46 +0000 (11:10 -0800)
`ReadOnlySequence<T>.Length` isn't as small or fast as `ReadOnlySpan<T>.Length`, which is just a field access.  Since we need the span anyway for the single element case, just get the span first and then compare with its length.

Commit migrated from https://github.com/dotnet/corefx/commit/7fc9d5730aabc6724edf18f5bedde6d32610f681

src/libraries/System.Memory/src/System/Buffers/BuffersExtensions.cs

index fc3f0ea..b8c5f8d 100644 (file)
@@ -63,12 +63,12 @@ namespace System.Buffers
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void CopyTo<T>(in this ReadOnlySequence<T> source, Span<T> destination)
         {
-            if (source.Length > destination.Length)
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destination);
-
             if (source.IsSingleSegment)
             {
-                source.First.Span.CopyTo(destination);
+                ReadOnlySpan<T> span = source.First.Span;
+                if (span.Length > destination.Length)
+                    ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destination);
+                span.CopyTo(destination);
             }
             else
             {
@@ -78,6 +78,9 @@ namespace System.Buffers
 
         private static void CopyToMultiSegment<T>(in ReadOnlySequence<T> sequence, Span<T> destination)
         {
+            if (sequence.Length > destination.Length)
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destination);
+
             SequencePosition position = sequence.Start;
             while (sequence.TryGet(ref position, out ReadOnlyMemory<T> memory))
             {