From 239b691ff5de11f1b23182016c7bc31f4dc20094 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 7 Apr 2017 08:35:53 -0700 Subject: [PATCH] A few HttpParser changes (#1624) - Renamed KestrelHttpParser to HttpParser - Removed the generic virtual dispatch as it turns out to be an order of magnitude slower than regular virtual dispatch. This change means we also lose the inlining of Frame.OnStartLine and Frame.OnHeader. --- .../Http/{KestrelHttpParser.cs => HttpParser.cs} | 12 ++++++------ .../Internal/Http/IHttpParser.cs | 4 ++-- .../KestrelServer.cs | 2 +- .../FrameResponseHeadersTests.cs | 4 ++-- .../HttpParserTests.cs | 2 +- .../FrameParsingOverheadBenchmark.cs | 4 ++-- .../FrameWritingBenchmark.cs | 2 +- .../KestrelHttpParserBenchmark.cs | 2 +- .../RequestParsingBenchmark.cs | 2 +- .../ResponseHeaderCollectionBenchmark.cs | 2 +- .../ResponseHeadersWritingBenchmark.cs | 2 +- test/shared/TestServiceContext.cs | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) rename src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/{KestrelHttpParser.cs => HttpParser.cs} (96%) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/KestrelHttpParser.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/HttpParser.cs similarity index 96% rename from src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/KestrelHttpParser.cs rename to src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/HttpParser.cs index 346a0abfe8..f5ac574008 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/KestrelHttpParser.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/HttpParser.cs @@ -10,9 +10,9 @@ using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { - public class KestrelHttpParser : IHttpParser + public class HttpParser : IHttpParser { - public KestrelHttpParser(IKestrelTrace log) + public HttpParser(IKestrelTrace log) { Log = log; } @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http private const byte ByteQuestionMark = (byte)'?'; private const byte BytePercentage = (byte)'%'; - public unsafe bool ParseRequestLine(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler + public unsafe bool ParseRequestLine(IHttpRequestLineHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { consumed = buffer.Start; examined = buffer.End; @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http return true; } - private unsafe void ParseRequestLine(T handler, byte* data, int length) where T : IHttpRequestLineHandler + private unsafe void ParseRequestLine(IHttpRequestLineHandler handler, byte* data, int length) { int offset; Span customMethod = default(Span); @@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http handler.OnStartLine(method, httpVersion, targetBuffer, pathBuffer, query, customMethod, pathEncoded); } - public unsafe bool ParseHeaders(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) where T : IHttpHeadersHandler + public unsafe bool ParseHeaders(IHttpHeadersHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) { consumed = buffer.Start; examined = buffer.End; @@ -347,7 +347,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe void TakeSingleHeader(byte* headerLine, int length, T handler) where T : IHttpHeadersHandler + private unsafe void TakeSingleHeader(byte* headerLine, int length, IHttpHeadersHandler handler) { // Skip CR, LF from end position var valueEnd = length - 3; diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/IHttpParser.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/IHttpParser.cs index f9b8ec2e21..8473fc4cc3 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/IHttpParser.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/IHttpParser.cs @@ -7,9 +7,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { public interface IHttpParser { - bool ParseRequestLine(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler; + bool ParseRequestLine(IHttpRequestLineHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined); - bool ParseHeaders(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) where T : IHttpHeadersHandler; + bool ParseHeaders(IHttpHeadersHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes); void Reset(); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Core/KestrelServer.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Core/KestrelServer.cs index d84f6f7a19..8cb36edf33 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Core/KestrelServer.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Core/KestrelServer.cs @@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core var serviceContext = new ServiceContext { Log = trace, - HttpParserFactory = frame => new KestrelHttpParser(frame.ServiceContext.Log), + HttpParserFactory = frame => new HttpParser(frame.ServiceContext.Log), ThreadPool = threadPool, DateHeaderValueManager = _dateHeaderValueManager, ServerOptions = Options diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/FrameResponseHeadersTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/FrameResponseHeadersTests.cs index 7ca2c6eed7..c36da4188f 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/FrameResponseHeadersTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/FrameResponseHeadersTests.cs @@ -259,7 +259,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests private class NoopHttpParser : IHttpParser { - public bool ParseHeaders(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) where T : IHttpHeadersHandler + public bool ParseHeaders(IHttpHeadersHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) { consumed = buffer.Start; examined = buffer.End; @@ -267,7 +267,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests return false; } - public bool ParseRequestLine(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler + public bool ParseRequestLine(IHttpRequestLineHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { consumed = buffer.Start; examined = buffer.End; diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/HttpParserTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/HttpParserTests.cs index 8ef554e4f5..3600be4c40 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/HttpParserTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests/HttpParserTests.cs @@ -418,7 +418,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests Assert.Equal(buffer.End, examined); } - private IHttpParser CreateParser(IKestrelTrace log) => new KestrelHttpParser(log); + private IHttpParser CreateParser(IKestrelTrace log) => new HttpParser(log); public static IEnumerable RequestLineValidData => HttpParsingData.RequestLineValidData; diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameParsingOverheadBenchmark.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameParsingOverheadBenchmark.cs index f777f6b370..1e05f8ea99 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameParsingOverheadBenchmark.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameParsingOverheadBenchmark.cs @@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance public static readonly NullParser Instance = new NullParser(); - public bool ParseHeaders(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) where T : IHttpHeadersHandler + public bool ParseHeaders(IHttpHeadersHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) { handler.OnHeader(new Span(_hostHeaderName), new Span(_hostHeaderValue)); handler.OnHeader(new Span(_acceptHeaderName), new Span(_acceptHeaderValue)); @@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance return true; } - public bool ParseRequestLine(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler + public bool ParseRequestLine(IHttpRequestLineHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { handler.OnStartLine(HttpMethod.Get, HttpVersion.Http11, diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameWritingBenchmark.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameWritingBenchmark.cs index 72973e444a..01f1b008fa 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameWritingBenchmark.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/FrameWritingBenchmark.cs @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance DateHeaderValueManager = new DateHeaderValueManager(), ServerOptions = new KestrelServerOptions(), Log = new MockTrace(), - HttpParserFactory = f => new KestrelHttpParser(log: null) + HttpParserFactory = f => new HttpParser(log: null) }; var frameContext = new FrameContext { diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/KestrelHttpParserBenchmark.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/KestrelHttpParserBenchmark.cs index 852fadd6d6..d7e3e89511 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/KestrelHttpParserBenchmark.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/KestrelHttpParserBenchmark.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance public class KestrelHttpParserBenchmark : IHttpRequestLineHandler, IHttpHeadersHandler { - private readonly KestrelHttpParser _parser = new KestrelHttpParser(log: null); + private readonly HttpParser _parser = new HttpParser(log: null); private ReadableBuffer _buffer; diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsingBenchmark.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsingBenchmark.cs index 2222e73e84..78844fe659 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsingBenchmark.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/RequestParsingBenchmark.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance { var serviceContext = new ServiceContext { - HttpParserFactory = f => new KestrelHttpParser(f.ServiceContext.Log), + HttpParserFactory = f => new HttpParser(f.ServiceContext.Log), ServerOptions = new KestrelServerOptions() }; var frameContext = new FrameContext diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeaderCollectionBenchmark.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeaderCollectionBenchmark.cs index e1bd6e60dc..0d32ed7079 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeaderCollectionBenchmark.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeaderCollectionBenchmark.cs @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance { var serviceContext = new ServiceContext { - HttpParserFactory = f => new KestrelHttpParser(f.ServiceContext.Log), + HttpParserFactory = f => new HttpParser(f.ServiceContext.Log), ServerOptions = new KestrelServerOptions() }; var frameContext = new FrameContext diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeadersWritingBenchmark.cs b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeadersWritingBenchmark.cs index 75b32c4d0f..da56c4cc0b 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeadersWritingBenchmark.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.Performance/ResponseHeadersWritingBenchmark.cs @@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance DateHeaderValueManager = new DateHeaderValueManager(), ServerOptions = new KestrelServerOptions(), Log = new MockTrace(), - HttpParserFactory = f => new KestrelHttpParser(log: null) + HttpParserFactory = f => new HttpParser(log: null) }; var frameContext = new FrameContext diff --git a/test/shared/TestServiceContext.cs b/test/shared/TestServiceContext.cs index 9223ad87f4..bf8e8eed40 100644 --- a/test/shared/TestServiceContext.cs +++ b/test/shared/TestServiceContext.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Testing ThreadPool = new LoggingThreadPool(Log); DateHeaderValueManager = new DateHeaderValueManager(systemClock: new MockSystemClock()); DateHeaderValue = DateHeaderValueManager.GetDateHeaderValues().String; - HttpParserFactory = frame => new KestrelHttpParser(frame.ServiceContext.Log); + HttpParserFactory = frame => new HttpParser(frame.ServiceContext.Log); ServerOptions = new KestrelServerOptions { AddServerHeader = false