From 13519b6079043f6b800b70011175912abed57e19 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 7 Mar 2017 17:39:56 -0800 Subject: [PATCH] Fix CopyTo implementation in benchmark. (#1462) * wip * ooops --- ...pNetCore.Server.Kestrel.Performance.csproj | 3 +- .../RequestParsing.cs | 2 +- .../WritableBufferExtensions.cs | 63 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Server.Kestrel.Performance/WritableBufferExtensions.cs diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/Microsoft.AspNetCore.Server.Kestrel.Performance.csproj b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/Microsoft.AspNetCore.Server.Kestrel.Performance.csproj index 746c59cd10..e010d7fce2 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/Microsoft.AspNetCore.Server.Kestrel.Performance.csproj +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/Microsoft.AspNetCore.Server.Kestrel.Performance.csproj @@ -1,4 +1,4 @@ - + @@ -6,6 +6,7 @@ netcoreapp1.1 Exe true + true false diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsing.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsing.cs index 90bd7a16c5..8fc4bc0eea 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsing.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsing.cs @@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance private void InsertData(byte[] bytes) { var buffer = Pipe.Writer.Alloc(2048); - buffer.Write(bytes); + buffer.WriteFast(bytes); // There should not be any backpressure and task completes immediately buffer.FlushAsync().GetAwaiter().GetResult(); } diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/WritableBufferExtensions.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/WritableBufferExtensions.cs new file mode 100644 index 0000000000..04a538e4be --- /dev/null +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/WritableBufferExtensions.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.IO.Pipelines; +using System.Text; + +namespace Microsoft.AspNetCore.Server.Kestrel.Performance +{ + internal static class WritableBufferExtensions + { + public static void WriteFast(this WritableBuffer buffer, ReadOnlySpan source) + { + if (buffer.Memory.IsEmpty) + { + buffer.Ensure(); + } + + // Fast path, try copying to the available memory directly + if (source.Length <= buffer.Memory.Length) + { + source.CopyToFast(buffer.Memory.Span); + buffer.Advance(source.Length); + return; + } + + var remaining = source.Length; + var offset = 0; + + while (remaining > 0) + { + var writable = Math.Min(remaining, buffer.Memory.Length); + + buffer.Ensure(writable); + + if (writable == 0) + { + continue; + } + + source.Slice(offset, writable).CopyToFast(buffer.Memory.Span); + + remaining -= writable; + offset += writable; + + buffer.Advance(writable); + } + } + + private unsafe static void CopyToFast(this ReadOnlySpan source, Span destination) + { + if (destination.Length < source.Length) + { + throw new InvalidOperationException(); + } + + // Assume it fits + fixed (byte* pSource = &source.DangerousGetPinnableReference()) + fixed (byte* pDest = &destination.DangerousGetPinnableReference()) + { + Buffer.MemoryCopy(pSource, pDest, destination.Length, source.Length); + } + } + } +}