Browse Source

Speedup platform (#3740)

Sébastien Ros 7 years ago
parent
commit
b48c769720

+ 171 - 0
frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs

@@ -0,0 +1,171 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Buffers;
+using System.IO.Pipelines;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
+
+namespace PlatformBenchmarks
+{
+    public partial class BenchmarkApplication : IHttpConnection
+    {
+        private State _state;
+
+        public PipeReader Reader { get; set; }
+        public PipeWriter Writer { get; set; }
+
+        private HttpParser<ParsingAdapter> Parser { get; } = new HttpParser<ParsingAdapter>();
+
+        public async Task ExecuteAsync()
+        {
+            try
+            {
+                await ProcessRequestsAsync();
+
+                Reader.Complete();
+            }
+            catch (Exception ex)
+            {
+                Reader.Complete(ex);
+            }
+            finally
+            {
+                Writer.Complete();
+            }
+        }
+
+        private async Task ProcessRequestsAsync()
+        {
+            while (true)
+            {
+                var task = Reader.ReadAsync();
+
+                if (!task.IsCompleted)
+                {
+                    // No more data in the input
+                    await OnReadCompletedAsync();
+                }
+
+                var result = await task;
+                if (!ParseHttpRequest(ref result))
+                {
+                    break;
+                }
+
+                if (_state == State.Body)
+                {
+                    await ProcessRequestAsync();
+
+                    _state = State.StartLine;
+                }
+            }
+        }
+
+        // Should be `in` but ReadResult isn't readonly struct
+        private bool ParseHttpRequest(ref ReadResult result)
+        {
+            var buffer = result.Buffer;
+            var consumed = buffer.Start;
+            var examined = buffer.End;
+            var state = _state;
+
+            if (!buffer.IsEmpty)
+            {
+                var parsingStartLine = state == State.StartLine;
+                if (parsingStartLine)
+                {
+                    if (Parser.ParseRequestLine(new ParsingAdapter(this), buffer, out consumed, out examined))
+                    {
+                        state = State.Headers;
+                    }
+                }
+
+                if (state == State.Headers)
+                {
+                    if (parsingStartLine)
+                    {
+                        buffer = buffer.Slice(consumed);
+                    }
+
+                    if (Parser.ParseHeaders(new ParsingAdapter(this), buffer, out consumed, out examined, out int consumedBytes))
+                    {
+                        state = State.Body;
+                    }
+                }
+
+                if (state != State.Body && result.IsCompleted)
+                {
+                    ThrowUnexpectedEndOfData();
+                }
+            }
+            else if (result.IsCompleted)
+            {
+                return false;
+            }
+
+            _state = state;
+            Reader.AdvanceTo(consumed, examined);
+            return true;
+        }
+
+        public void OnHeader(Span<byte> name, Span<byte> value)
+        {
+        }
+
+        public async ValueTask OnReadCompletedAsync()
+        {
+            await Writer.FlushAsync();
+        }
+
+        private static void ThrowUnexpectedEndOfData()
+        {
+            throw new InvalidOperationException("Unexpected end of data!");
+        }
+
+        private enum State
+        {
+            StartLine,
+            Headers,
+            Body
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static BufferWriter<WriterAdapter> GetWriter(PipeWriter pipeWriter)
+            => new BufferWriter<WriterAdapter>(new WriterAdapter(pipeWriter));
+
+        private struct WriterAdapter : IBufferWriter<byte>
+        {
+            public PipeWriter Writer;
+
+            public WriterAdapter(PipeWriter writer)
+                => Writer = writer;
+
+            public void Advance(int count)
+                => Writer.Advance(count);
+
+            public Memory<byte> GetMemory(int sizeHint = 0)
+                => Writer.GetMemory(sizeHint);
+
+            public Span<byte> GetSpan(int sizeHint = 0)
+                => Writer.GetSpan(sizeHint);
+        }
+
+        private struct ParsingAdapter : IHttpRequestLineHandler, IHttpHeadersHandler
+        {
+            public BenchmarkApplication RequestHandler;
+
+            public ParsingAdapter(BenchmarkApplication requestHandler)
+                => RequestHandler = requestHandler;
+
+            public void OnHeader(Span<byte> name, Span<byte> value)
+                => RequestHandler.OnHeader(name, value);
+
+            public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
+                => RequestHandler.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
+        }
+    }
+
+}

+ 34 - 34
frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.cs

@@ -2,7 +2,6 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 
 using System;
 using System;
-using System.Buffers;
 using System.IO.Pipelines;
 using System.IO.Pipelines;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
@@ -10,8 +9,11 @@ using Utf8Json;
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {
-    public class BenchmarkApplication : HttpConnection
+    public partial class BenchmarkApplication
     {
     {
+        private readonly static AsciiString _applicationName = "Kestrel Platform-Level Application";
+        public static AsciiString ApplicationName => _applicationName;
+
         private readonly static AsciiString _crlf = "\r\n";
         private readonly static AsciiString _crlf = "\r\n";
         private readonly static AsciiString _eoh = "\r\n\r\n"; // End Of Headers
         private readonly static AsciiString _eoh = "\r\n\r\n"; // End Of Headers
         private readonly static AsciiString _http11OK = "HTTP/1.1 200 OK\r\n";
         private readonly static AsciiString _http11OK = "HTTP/1.1 200 OK\r\n";
@@ -21,46 +23,41 @@ namespace PlatformBenchmarks
         private readonly static AsciiString _headerContentTypeText = "Content-Type: text/plain\r\n";
         private readonly static AsciiString _headerContentTypeText = "Content-Type: text/plain\r\n";
         private readonly static AsciiString _headerContentTypeJson = "Content-Type: application/json\r\n";
         private readonly static AsciiString _headerContentTypeJson = "Content-Type: application/json\r\n";
 
 
-
         private readonly static AsciiString _plainTextBody = "Hello, World!";
         private readonly static AsciiString _plainTextBody = "Hello, World!";
 
 
-        private static class Paths
+        public static class Paths
         {
         {
             public readonly static AsciiString Plaintext = "/plaintext";
             public readonly static AsciiString Plaintext = "/plaintext";
             public readonly static AsciiString Json = "/json";
             public readonly static AsciiString Json = "/json";
         }
         }
 
 
-        private bool _isPlainText;
-        private bool _isJson;
+        private RequestType _requestType;
 
 
-        public override void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
+        public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
         {
         {
-            if (path.StartsWith(Paths.Plaintext) && method == HttpMethod.Get)
-            {
-                _isPlainText = true;
-            }
-            else if (path.StartsWith(Paths.Json) && method == HttpMethod.Get)
+            var requestType = RequestType.NotRecognized;
+            if (method == HttpMethod.Get)
             {
             {
-                _isJson = true;
+                if (Paths.Plaintext.Length <= path.Length && path.StartsWith(Paths.Plaintext))
+                {
+                    requestType = RequestType.PlainText;
+                }
+                else if (Paths.Json.Length <= path.Length && path.StartsWith(Paths.Json))
+                {
+                    requestType = RequestType.Json;
+                }
             }
             }
-            else
-            {
-                _isPlainText = false;
-                _isJson = false;
-            }
-        }
 
 
-        public override void OnHeader(Span<byte> name, Span<byte> value)
-        {
+            _requestType = requestType;
         }
         }
 
 
-        public override ValueTask ProcessRequestAsync()
+        public ValueTask ProcessRequestAsync()
         {
         {
-            if (_isPlainText)
+            if (_requestType == RequestType.PlainText)
             {
             {
                 PlainText(Writer);
                 PlainText(Writer);
             }
             }
-            else if (_isJson)
+            else if (_requestType == RequestType.Json)
             {
             {
                 Json(Writer);
                 Json(Writer);
             }
             }
@@ -72,14 +69,10 @@ namespace PlatformBenchmarks
             return default;
             return default;
         }
         }
 
 
-        public override async ValueTask OnReadCompletedAsync()
-        {
-            await Writer.FlushAsync();
-        }
-
         private static void PlainText(PipeWriter pipeWriter)
         private static void PlainText(PipeWriter pipeWriter)
         {
         {
-            var writer = new BufferWriter<PipeWriter>(pipeWriter);
+            var writer = GetWriter(pipeWriter);
+
             // HTTP 1.1 OK
             // HTTP 1.1 OK
             writer.Write(_http11OK);
             writer.Write(_http11OK);
 
 
@@ -94,7 +87,7 @@ namespace PlatformBenchmarks
 
 
             // Content-Length header
             // Content-Length header
             writer.Write(_headerContentLength);
             writer.Write(_headerContentLength);
-            writer.WriteNumeric((ulong)_plainTextBody.Length);
+            writer.WriteNumeric((uint)_plainTextBody.Length);
 
 
             // End of headers
             // End of headers
             writer.Write(_eoh);
             writer.Write(_eoh);
@@ -106,7 +99,7 @@ namespace PlatformBenchmarks
 
 
         private static void Json(PipeWriter pipeWriter)
         private static void Json(PipeWriter pipeWriter)
         {
         {
-            var writer = new BufferWriter<PipeWriter>(pipeWriter);
+            var writer = GetWriter(pipeWriter);
 
 
             // HTTP 1.1 OK
             // HTTP 1.1 OK
             writer.Write(_http11OK);
             writer.Write(_http11OK);
@@ -123,7 +116,7 @@ namespace PlatformBenchmarks
             // Content-Length header
             // Content-Length header
             writer.Write(_headerContentLength);
             writer.Write(_headerContentLength);
             var jsonPayload = JsonSerializer.SerializeUnsafe(new { message = "Hello, World!" });
             var jsonPayload = JsonSerializer.SerializeUnsafe(new { message = "Hello, World!" });
-            writer.WriteNumeric((ulong)jsonPayload.Count);
+            writer.WriteNumeric((uint)jsonPayload.Count);
 
 
             // End of headers
             // End of headers
             writer.Write(_eoh);
             writer.Write(_eoh);
@@ -135,7 +128,7 @@ namespace PlatformBenchmarks
 
 
         private static void Default(PipeWriter pipeWriter)
         private static void Default(PipeWriter pipeWriter)
         {
         {
-            var writer = new BufferWriter<PipeWriter>(pipeWriter);
+            var writer = GetWriter(pipeWriter);
 
 
             // HTTP 1.1 OK
             // HTTP 1.1 OK
             writer.Write(_http11OK);
             writer.Write(_http11OK);
@@ -153,5 +146,12 @@ namespace PlatformBenchmarks
             writer.Write(_crlf);
             writer.Write(_crlf);
             writer.Commit();
             writer.Commit();
         }
         }
+
+        private enum RequestType
+        {
+            NotRecognized,
+            PlainText,
+            Json
+        }
     }
     }
 }
 }

+ 104 - 0
frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferExtensions.cs

@@ -0,0 +1,104 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Buffers;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace PlatformBenchmarks
+{
+    // Same as KestrelHttpServer\src\Kestrel.Core\Internal\Http\PipelineExtensions.cs
+    // However methods accept T : struct, IBufferWriter<byte> rather than PipeWriter.
+    // This allows a struct wrapper to turn CountingBufferWriter into a non-shared generic,
+    // while still offering the WriteNumeric extension.
+
+    public static class BufferExtensions
+    {
+        private const int _maxULongByteLength = 20;
+
+        [ThreadStatic]
+        private static byte[] _numericBytesScratch;
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static unsafe void WriteNumeric<T>(ref this BufferWriter<T> buffer, uint number)
+             where T : struct, IBufferWriter<byte>
+        {
+            const byte AsciiDigitStart = (byte)'0';
+
+            var span = buffer.Span;
+            var bytesLeftInBlock = span.Length;
+
+            // Fast path, try copying to the available memory directly
+            var advanceBy = 0;
+            fixed (byte* output = &MemoryMarshal.GetReference(span))
+            {
+                var start = output;
+                if (number < 10 && bytesLeftInBlock >= 1)
+                {
+                    start[0] = (byte)(number + AsciiDigitStart);
+                    advanceBy = 1;
+                }
+                else if (number < 100 && bytesLeftInBlock >= 2)
+                {
+                    var tens = (byte)((number * 205u) >> 11); // div10, valid to 1028
+
+                    start[0] = (byte)(tens + AsciiDigitStart);
+                    start[1] = (byte)(number - (tens * 10) + AsciiDigitStart);
+                    advanceBy = 2;
+                }
+                else if (number < 1000 && bytesLeftInBlock >= 3)
+                {
+                    var digit0 = (byte)((number * 41u) >> 12); // div100, valid to 1098
+                    var digits01 = (byte)((number * 205u) >> 11); // div10, valid to 1028
+
+                    start[0] = (byte)(digit0 + AsciiDigitStart);
+                    start[1] = (byte)(digits01 - (digit0 * 10) + AsciiDigitStart);
+                    start[2] = (byte)(number - (digits01 * 10) + AsciiDigitStart);
+                    advanceBy = 3;
+                }
+            }
+
+            if (advanceBy > 0)
+            {
+                buffer.Advance(advanceBy);
+            }
+            else
+            {
+                WriteNumericMultiWrite(ref buffer, number);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void WriteNumericMultiWrite<T>(ref this BufferWriter<T> buffer, uint number)
+             where T : struct, IBufferWriter<byte>
+        {
+            const byte AsciiDigitStart = (byte)'0';
+
+            var value = number;
+            var position = _maxULongByteLength;
+            var byteBuffer = NumericBytesScratch;
+            do
+            {
+                // Consider using Math.DivRem() if available
+                var quotient = value / 10;
+                byteBuffer[--position] = (byte)(AsciiDigitStart + (value - quotient * 10)); // 0x30 = '0'
+                value = quotient;
+            }
+            while (value != 0);
+
+            var length = _maxULongByteLength - position;
+            buffer.Write(new ReadOnlySpan<byte>(byteBuffer, position, length));
+        }
+
+        private static byte[] NumericBytesScratch => _numericBytesScratch ?? CreateNumericBytesScratch();
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static byte[] CreateNumericBytesScratch()
+        {
+            var bytes = new byte[_maxULongByteLength];
+            _numericBytesScratch = bytes;
+            return bytes;
+        }
+    }
+}

+ 6 - 5
frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferWriter.cs

@@ -1,12 +1,13 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 
+using System;
+using System.Buffers;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 
 
-namespace System.Buffers
+namespace PlatformBenchmarks
 {
 {
-    internal ref struct BufferWriter<T> where T: IBufferWriter<byte>
+    public ref struct BufferWriter<T> where T : IBufferWriter<byte>
     {
     {
         private T _output;
         private T _output;
         private Span<byte> _span;
         private Span<byte> _span;

+ 0 - 38
frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferWriterExtensions.cs

@@ -1,38 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.Buffers.Text;
-using System.Diagnostics;
-using System.IO.Pipelines;
-using System.Runtime.CompilerServices;
-
-namespace System.Buffers
-{
-    internal static class BufferWriterExtensions
-    {
-        private const int MaxULongByteLength = 20;
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static void WriteNumeric(ref this BufferWriter<PipeWriter> buffer, ulong number)
-        {
-            // Try to format directly
-            if (Utf8Formatter.TryFormat(number, buffer.Span, out int bytesWritten))
-            {
-                buffer.Advance(bytesWritten);
-            }
-            else
-            {
-                // Ask for at least 20 bytes
-                buffer.Ensure(MaxULongByteLength);
-
-                Debug.Assert(buffer.Span.Length >= 20, "Buffer is < 20 bytes");
-
-                // Try again
-                if (Utf8Formatter.TryFormat(number, buffer.Span, out bytesWritten))
-                {
-                    buffer.Advance(bytesWritten);
-                }
-            }
-        }
-    }
-}

+ 5 - 2
frameworks/CSharp/aspnetcore/PlatformBenchmarks/DateHeader.cs

@@ -37,15 +37,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             s_headerBytesScratch[suffixIndex] = (byte)'\r';
             s_headerBytesScratch[suffixIndex] = (byte)'\r';
             s_headerBytesScratch[suffixIndex + 1] = (byte)'\n';
             s_headerBytesScratch[suffixIndex + 1] = (byte)'\n';
             SetDateValues(DateTimeOffset.UtcNow);
             SetDateValues(DateTimeOffset.UtcNow);
+            SyncDateTimer();
         }
         }
 
 
+        public static void SyncDateTimer() => s_timer.Change(1000, 1000);
+
         public static ReadOnlySpan<byte> HeaderBytes => s_headerBytesMaster;
         public static ReadOnlySpan<byte> HeaderBytes => s_headerBytesMaster;
 
 
         private static void SetDateValues(DateTimeOffset value)
         private static void SetDateValues(DateTimeOffset value)
         {
         {
             lock (s_headerBytesScratch)
             lock (s_headerBytesScratch)
             {
             {
-                if (!Utf8Formatter.TryFormat(value, s_headerBytesScratch.AsSpan().Slice(prefixLength), out int written, 'R'))
+                if (!Utf8Formatter.TryFormat(value, s_headerBytesScratch.AsSpan(prefixLength), out int written, 'R'))
                 {
                 {
                     throw new Exception("date time format failed");
                     throw new Exception("date time format failed");
                 }
                 }
@@ -56,4 +59,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             }
             }
         }
         }
     }
     }
-}
+}

+ 2 - 134
frameworks/CSharp/aspnetcore/PlatformBenchmarks/HttpApplication.cs

@@ -1,161 +1,29 @@
 // Copyright (c) .NET Foundation. All rights reserved.
 // Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 
-using System;
-using System.Buffers;
-using System.IO.Pipelines;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Connections;
 using Microsoft.AspNetCore.Connections;
-using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {
     public static class HttpApplicationConnectionBuilderExtensions
     public static class HttpApplicationConnectionBuilderExtensions
     {
     {
-        public static IConnectionBuilder UseHttpApplication<TConnection>(this IConnectionBuilder builder) where TConnection : HttpConnection, new()
+        public static IConnectionBuilder UseHttpApplication<TConnection>(this IConnectionBuilder builder) where TConnection : IHttpConnection, new()
         {
         {
             return builder.Use(next => new HttpApplication<TConnection>().ExecuteAsync);
             return builder.Use(next => new HttpApplication<TConnection>().ExecuteAsync);
         }
         }
     }
     }
 
 
-    public class HttpApplication<TConnection> where TConnection : HttpConnection, new()
+    public class HttpApplication<TConnection> where TConnection : IHttpConnection, new()
     {
     {
         public Task ExecuteAsync(ConnectionContext connection)
         public Task ExecuteAsync(ConnectionContext connection)
         {
         {
-            var parser = new HttpParser<HttpConnection>();
-
             var httpConnection = new TConnection
             var httpConnection = new TConnection
             {
             {
-                Parser = parser,
                 Reader = connection.Transport.Input,
                 Reader = connection.Transport.Input,
                 Writer = connection.Transport.Output
                 Writer = connection.Transport.Output
             };
             };
             return httpConnection.ExecuteAsync();
             return httpConnection.ExecuteAsync();
         }
         }
     }
     }
-
-    public class HttpConnection : IHttpHeadersHandler, IHttpRequestLineHandler
-    {
-        private State _state;
-
-        public PipeReader Reader { get; set; }
-        public PipeWriter Writer { get; set; }
-
-        internal HttpParser<HttpConnection> Parser { get; set; }
-
-        public virtual void OnHeader(Span<byte> name, Span<byte> value)
-        {
-
-        }
-
-        public virtual void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
-        {
-
-        }
-
-        public virtual ValueTask ProcessRequestAsync()
-        {
-            return default;
-        }
-
-        public virtual ValueTask OnReadCompletedAsync()
-        {
-            return default;
-        }
-
-        public async Task ExecuteAsync()
-        {
-            try
-            {
-                await ProcessRequestsAsync();
-
-                Reader.Complete();
-            }
-            catch (Exception ex)
-            {
-                Reader.Complete(ex);
-            }
-            finally
-            {
-                Writer.Complete();
-            }
-        }
-
-        private async Task ProcessRequestsAsync()
-        {
-            while (true)
-            {
-                var task = Reader.ReadAsync();
-
-                if (!task.IsCompleted)
-                {
-                    // No more data in the input
-                    await OnReadCompletedAsync();
-                }
-
-                var result = await task;
-                var buffer = result.Buffer;
-                var consumed = buffer.Start;
-                var examined = buffer.End;
-
-                if (!buffer.IsEmpty)
-                {
-                    ParseHttpRequest(buffer, out consumed, out examined);
-
-                    if (_state != State.Body && result.IsCompleted)
-                    {
-                        ThrowUnexpectedEndOfData();
-                    }
-                }
-                else if (result.IsCompleted)
-                {
-                    break;
-                }
-
-                Reader.AdvanceTo(consumed, examined);
-
-                if (_state == State.Body)
-                {
-                    await ProcessRequestAsync();
-
-                    _state = State.StartLine;
-                }
-            }
-        }
-
-        private void ParseHttpRequest(in ReadOnlySequence<byte> buffer, out SequencePosition consumed, out SequencePosition examined)
-        {
-            consumed = buffer.Start;
-            examined = buffer.End;
-
-            var parsingStartLine = _state == State.StartLine;
-            if (parsingStartLine)
-            {
-                if (Parser.ParseRequestLine(this, buffer, out consumed, out examined))
-                {
-                    _state = State.Headers;
-                }
-            }
-
-            if (_state == State.Headers)
-            {
-                if (Parser.ParseHeaders(this, parsingStartLine ? buffer.Slice(consumed) : buffer, out consumed, out examined, out int consumedBytes))
-                {
-                    _state = State.Body;
-                }
-            }
-        }
-
-        private static void ThrowUnexpectedEndOfData()
-        {
-            throw new InvalidOperationException("Unexpected end of data!");
-        }
-
-        private enum State
-        {
-            StartLine,
-            Headers,
-            Body
-        }
-    }
 }
 }

+ 17 - 0
frameworks/CSharp/aspnetcore/PlatformBenchmarks/IHttpConnection.cs

@@ -0,0 +1,17 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.IO.Pipelines;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
+
+namespace PlatformBenchmarks
+{
+    public interface IHttpConnection : IHttpHeadersHandler, IHttpRequestLineHandler
+    {
+        PipeReader Reader { get; set; }
+        PipeWriter Writer { get; set; }
+        Task ExecuteAsync();
+        ValueTask OnReadCompletedAsync();
+    }
+}

+ 6 - 4
frameworks/CSharp/aspnetcore/PlatformBenchmarks/Program.cs

@@ -3,12 +3,9 @@
 
 
 using System;
 using System;
 using System.Net;
 using System.Net;
-using Microsoft.AspNetCore;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Server.Kestrel.Core;
-using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {
@@ -16,6 +13,11 @@ namespace PlatformBenchmarks
     {
     {
         public static void Main(string[] args)
         public static void Main(string[] args)
         {
         {
+            Console.WriteLine(BenchmarkApplication.ApplicationName);
+            Console.WriteLine(BenchmarkApplication.Paths.Plaintext);
+            Console.WriteLine(BenchmarkApplication.Paths.Json);
+            DateHeader.SyncDateTimer();
+
             BuildWebHost(args).Run();
             BuildWebHost(args).Run();
         }
         }
 
 

+ 0 - 3
frameworks/CSharp/aspnetcore/PlatformBenchmarks/Startup.cs

@@ -2,10 +2,7 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 
 using System;
 using System;
-using System.Net.WebSockets;
-using System.Threading.Tasks;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {