Browse Source

CoreRt eagerly create SequenceReader (#5616)

Ben Adams 5 years ago
parent
commit
72a7282fd9

+ 58 - 11
frameworks/CSharp/aspnetcore-corert/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs

@@ -7,6 +7,7 @@ using System.IO.Pipelines;
 using System.Runtime.CompilerServices;
 using System.Text.Encodings.Web;
 using System.Text.Unicode;
+using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 
@@ -53,26 +54,32 @@ namespace PlatformBenchmarks
         {
             while (true)
             {
-                var readResult = await Reader.ReadAsync();
+                var readResult = await Reader.ReadAsync(default);
+                var buffer = readResult.Buffer;
+                var isCompleted = readResult.IsCompleted;
 
-                if (!HandleRequest(readResult))
+                if (buffer.IsEmpty && isCompleted)
                 {
                     return;
                 }
 
-                await Writer.FlushAsync();
+                if (!HandleRequests(buffer, isCompleted))
+                {
+                    return;
+                }
+
+                await Writer.FlushAsync(default);
             }
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private bool HandleRequest(in ReadResult result)
+        private bool HandleRequests(in ReadOnlySequence<byte> buffer, bool isCompleted)
         {
-            var buffer = result.Buffer;
+            var reader = new SequenceReader<byte>(buffer);
             var writer = GetWriter(Writer);
 
             while (true)
             {
-                if (!ParseHttpRequest(ref buffer, result.IsCompleted, out var examined))
+                if (!ParseHttpRequest(ref reader, isCompleted))
                 {
                     return false;
                 }
@@ -83,7 +90,7 @@ namespace PlatformBenchmarks
 
                     _state = State.StartLine;
 
-                    if (!buffer.IsEmpty)
+                    if (!reader.End)
                     {
                         // More input data to parse
                         continue;
@@ -91,13 +98,52 @@ namespace PlatformBenchmarks
                 }
 
                 // No more input or incomplete data, Advance the Reader
-                Reader.AdvanceTo(buffer.Start, examined);
+                Reader.AdvanceTo(reader.Position, buffer.End);
                 break;
             }
 
             writer.Commit();
             return true;
         }
+
+        private bool ParseHttpRequest(ref SequenceReader<byte> reader, bool isCompleted)
+        {
+            var state = _state;
+
+            if (state == State.StartLine)
+            {
+#if NETCOREAPP5_0
+                var unconsumedSequence = reader.UnreadSequence;
+#else
+                var unconsumedSequence = reader.Sequence.Slice(reader.Position);
+#endif
+                if (Parser.ParseRequestLine(new ParsingAdapter(this), unconsumedSequence, out var consumed, out _))
+                {
+                    state = State.Headers;
+
+                    var parsedLength = unconsumedSequence.Slice(reader.Position, consumed).Length;
+                    reader.Advance(parsedLength);
+                }
+            }
+
+            if (state == State.Headers)
+            {
+                var success = Parser.ParseHeaders(new ParsingAdapter(this), ref reader);
+
+                if (success)
+                {
+                    state = State.Body;
+                }
+            }
+
+            if (state != State.Body && isCompleted)
+            {
+                ThrowUnexpectedEndOfData();
+            }
+
+            _state = state;
+            return true;
+        }
 #else
         private async Task ProcessRequestsAsync()
         {
@@ -134,7 +180,7 @@ namespace PlatformBenchmarks
                 await Writer.FlushAsync();
             }
         }
-#endif
+
         private bool ParseHttpRequest(ref ReadOnlySequence<byte> buffer, bool isCompleted, out SequencePosition examined)
         {
             examined = buffer.End;
@@ -185,6 +231,7 @@ namespace PlatformBenchmarks
             _state = state;
             return true;
         }
+#endif
 
 #if NETCOREAPP5_0
 
@@ -274,4 +321,4 @@ namespace PlatformBenchmarks
                 => RequestHandler.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
         }
     }
-}
+}