arespr/knownmethods-optimizations cleanup

This commit is contained in:
Stephen Halter 2017-04-27 12:39:36 -07:00
parent f464760bf8
commit 557cf29e4a
9 changed files with 54 additions and 74 deletions

View File

@ -1,44 +1,44 @@
// 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;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
public static partial class HttpUtilities public static partial class HttpUtilities
{ {
// readonly primitive statics can be Jit'd to consts https://github.com/dotnet/coreclr/issues/1079 // readonly primitive statics can be Jit'd to consts https://github.com/dotnet/coreclr/issues/1079
private readonly static ulong _httpConnectMethodLong = GetAsciiStringAsLong("CONNECT "); private static readonly ulong _httpConnectMethodLong = GetAsciiStringAsLong("CONNECT ");
private readonly static ulong _httpDeleteMethodLong = GetAsciiStringAsLong("DELETE \0"); private static readonly ulong _httpDeleteMethodLong = GetAsciiStringAsLong("DELETE \0");
private readonly static ulong _httpHeadMethodLong = GetAsciiStringAsLong("HEAD \0\0\0"); private static readonly ulong _httpHeadMethodLong = GetAsciiStringAsLong("HEAD \0\0\0");
private readonly static ulong _httpPatchMethodLong = GetAsciiStringAsLong("PATCH \0\0"); private static readonly ulong _httpPatchMethodLong = GetAsciiStringAsLong("PATCH \0\0");
private readonly static ulong _httpPostMethodLong = GetAsciiStringAsLong("POST \0\0\0"); private static readonly ulong _httpPostMethodLong = GetAsciiStringAsLong("POST \0\0\0");
private readonly static ulong _httpPutMethodLong = GetAsciiStringAsLong("PUT \0\0\0\0"); private static readonly ulong _httpPutMethodLong = GetAsciiStringAsLong("PUT \0\0\0\0");
private readonly static ulong _httpOptionsMethodLong = GetAsciiStringAsLong("OPTIONS "); private static readonly ulong _httpOptionsMethodLong = GetAsciiStringAsLong("OPTIONS ");
private readonly static ulong _httpTraceMethodLong = GetAsciiStringAsLong("TRACE \0\0"); private static readonly ulong _httpTraceMethodLong = GetAsciiStringAsLong("TRACE \0\0");
private readonly static ulong _mask8Chars = GetMaskAsLong(new byte[] private static readonly ulong _mask8Chars = GetMaskAsLong(new byte[]
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}); {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff});
private readonly static ulong _mask7Chars = GetMaskAsLong(new byte[] private static readonly ulong _mask7Chars = GetMaskAsLong(new byte[]
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}); {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00});
private readonly static ulong _mask6Chars = GetMaskAsLong(new byte[] private static readonly ulong _mask6Chars = GetMaskAsLong(new byte[]
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00}); {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00});
private readonly static ulong _mask5Chars = GetMaskAsLong(new byte[] private static readonly ulong _mask5Chars = GetMaskAsLong(new byte[]
{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}); {0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00});
private readonly static ulong _mask4Chars = GetMaskAsLong(new byte[] private static readonly ulong _mask4Chars = GetMaskAsLong(new byte[]
{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}); {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00});
private readonly static Tuple<ulong, ulong, HttpMethod, int>[] _knownMethods = private static readonly Tuple<ulong, ulong, HttpMethod, int>[] _knownMethods =
new Tuple<ulong, ulong, HttpMethod, int>[17]; new Tuple<ulong, ulong, HttpMethod, int>[17];
private readonly static string[] _methodNames = new string[9]; private static readonly string[] _methodNames = new string[9];
static HttpUtilities() static HttpUtilities()
{ {

View File

@ -5,7 +5,6 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System; using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
@ -20,10 +19,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
public const string HttpsUriScheme = "https://"; public const string HttpsUriScheme = "https://";
// readonly primitive statics can be Jit'd to consts https://github.com/dotnet/coreclr/issues/1079 // readonly primitive statics can be Jit'd to consts https://github.com/dotnet/coreclr/issues/1079
private readonly static ulong _httpSchemeLong = GetAsciiStringAsLong(HttpUriScheme + "\0"); private static readonly ulong _httpSchemeLong = GetAsciiStringAsLong(HttpUriScheme + "\0");
private readonly static ulong _httpsSchemeLong = GetAsciiStringAsLong(HttpsUriScheme); private static readonly ulong _httpsSchemeLong = GetAsciiStringAsLong(HttpsUriScheme);
private const uint _httpGetMethodInt = 542393671; // retun of GetAsciiStringAsInt("GET "); const results in better codegen private const uint _httpGetMethodInt = 542393671; // GetAsciiStringAsInt("GET "); const results in better codegen
private const ulong _http10VersionLong = 3471766442030158920; // GetAsciiStringAsLong("HTTP/1.0"); const results in better codegen private const ulong _http10VersionLong = 3471766442030158920; // GetAsciiStringAsLong("HTTP/1.0"); const results in better codegen
private const ulong _http11VersionLong = 3543824036068086856; // GetAsciiStringAsLong("HTTP/1.1"); const results in better codegen private const ulong _http11VersionLong = 3543824036068086856; // GetAsciiStringAsLong("HTTP/1.1"); const results in better codegen
@ -34,18 +33,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
_knownMethods[GetKnownMethodIndex(knownMethodUlong)] = new Tuple<ulong, ulong, HttpMethod, int>(mask, knownMethodUlong, knownMethod, length); _knownMethods[GetKnownMethodIndex(knownMethodUlong)] = new Tuple<ulong, ulong, HttpMethod, int>(mask, knownMethodUlong, knownMethod, length);
} }
private readonly static Tuple<ulong, ulong, HttpMethod, int>[] _knownMethods =
{
Tuple.Create(_mask4Chars, _httpPutMethodLong, HttpMethod.Put, 3),
Tuple.Create(_mask5Chars, _httpPostMethodLong, HttpMethod.Post, 4),
Tuple.Create(_mask5Chars, _httpHeadMethodLong, HttpMethod.Head, 4),
Tuple.Create(_mask6Chars, _httpTraceMethodLong, HttpMethod.Trace, 5),
Tuple.Create(_mask6Chars, _httpPatchMethodLong, HttpMethod.Patch, 5),
Tuple.Create(_mask7Chars, _httpDeleteMethodLong, HttpMethod.Delete, 6),
Tuple.Create(_mask8Chars, _httpConnectMethodLong, HttpMethod.Connect, 7),
Tuple.Create(_mask8Chars, _httpOptionsMethodLong, HttpMethod.Options, 7),
};
private static void FillKnownMethodsGaps() private static void FillKnownMethodsGaps()
{ {
var knownMethods = _knownMethods; var knownMethods = _knownMethods;
@ -60,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
private unsafe static ulong GetAsciiStringAsLong(string str) private static unsafe ulong GetAsciiStringAsLong(string str)
{ {
Debug.Assert(str.Length == 8, "String must be exactly 8 (ASCII) characters long."); Debug.Assert(str.Length == 8, "String must be exactly 8 (ASCII) characters long.");
@ -72,7 +59,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
private unsafe static uint GetAsciiStringAsInt(string str) private static unsafe uint GetAsciiStringAsInt(string str)
{ {
Debug.Assert(str.Length == 4, "String must be exactly 4 (ASCII) characters long."); Debug.Assert(str.Length == 4, "String must be exactly 4 (ASCII) characters long.");
@ -84,7 +71,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
private unsafe static ulong GetMaskAsLong(byte[] bytes) private static unsafe ulong GetMaskAsLong(byte[] bytes)
{ {
Debug.Assert(bytes.Length == 8, "Mask must be exactly 8 bytes long."); Debug.Assert(bytes.Length == 8, "Mask must be exactly 8 bytes long.");
@ -94,7 +81,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
public unsafe static string GetAsciiStringNonNullCharacters(this Span<byte> span) public static unsafe string GetAsciiStringNonNullCharacters(this Span<byte> span)
{ {
if (span.IsEmpty) if (span.IsEmpty)
{ {
@ -157,7 +144,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal unsafe static HttpMethod GetKnownMethod(byte* data, int length, out int methodLength) internal static unsafe HttpMethod GetKnownMethod(byte* data, int length, out int methodLength)
{ {
methodLength = 0; methodLength = 0;
if (length < sizeof(uint)) if (length < sizeof(uint))
@ -229,7 +216,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
/// </remarks> /// </remarks>
/// <returns><c>true</c> if the input matches a known string, <c>false</c> otherwise.</returns> /// <returns><c>true</c> if the input matches a known string, <c>false</c> otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal unsafe static HttpVersion GetKnownVersion(byte* location, int length) internal static unsafe HttpVersion GetKnownVersion(byte* location, int length)
{ {
HttpVersion knownVersion; HttpVersion knownVersion;
var version = *(ulong*)location; var version = *(ulong*)location;

View File

@ -15,9 +15,6 @@
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
</ItemGroup> </ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" /> <ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" /> <ProjectReference Include="..\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />

View File

@ -1,12 +1,13 @@
// 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Server.KestrelTests namespace Microsoft.AspNetCore.Server.KestrelTests

View File

@ -15,10 +15,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{ {
const string frameHeadersGeneratedPath = "../../../../../src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/FrameHeaders.Generated.cs"; const string frameHeadersGeneratedPath = "../../../../../src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/FrameHeaders.Generated.cs";
const string frameGeneratedPath = "../../../../../src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/Frame.Generated.cs"; const string frameGeneratedPath = "../../../../../src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/Frame.Generated.cs";
const string httpUtilitiesGeneratedPath = "../../../../../src/Microsoft.AspNetCore.Server.Kestrel/Internal/Infrastructure/HttpUtilities.Generated.cs"; const string httpUtilitiesGeneratedPath = "../../../../../src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Infrastructure/HttpUtilities.Generated.cs";
var testFrameHeadersGeneratedPath = Path.GetTempFileName(); var testFrameHeadersGeneratedPath = Path.GetTempFileName();
var testFrameGeneratedPath = Path.GetTempFileName(); var testFrameGeneratedPath = Path.GetTempFileName();
var testHttpUtilitiesGeneratedPath = Path.GetTempFileName(); var testHttpUtilitiesGeneratedPath = Path.GetTempFileName();
try try
{ {
var currentFrameHeadersGenerated = File.ReadAllText(frameHeadersGeneratedPath); var currentFrameHeadersGenerated = File.ReadAllText(frameHeadersGeneratedPath);

View File

@ -6,28 +6,21 @@
<TargetFramework>netcoreapp1.1</TargetFramework> <TargetFramework>netcoreapp1.1</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel.Core\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="$(AspNetCoreVersion)" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.Kestrel\Microsoft.AspNetCore.Server.Kestrel.csproj" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<StartWorkingDirectory>$(MSBuildThisFileDirectory)..\..\src\Microsoft.AspNetCore.Server.Kestrel.Core\Internal\Http</StartWorkingDirectory> <StartWorkingDirectory>$(MSBuildThisFileDirectory)..\..\src\Microsoft.AspNetCore.Server.Kestrel.Core</StartWorkingDirectory>
<StartArguments>FrameHeaders.Generated.cs Frame.Generated.cs</StartArguments> <StartArguments>Internal\Http\FrameHeaders.Generated.cs Internal\Http\Frame.Generated.cs Internal\Infrastructure\HttpUtilities.Generated.cs</StartArguments>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -1,4 +1,4 @@
// 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;
@ -10,11 +10,10 @@ namespace CodeGenerator.HttpUtilities
// C code for Algorithm L (Lexicographic combinations) in Section 7.2.1.3 of The Art of Computer Programming, Volume 4A: Combinatorial Algorithms, Part 1 : // C code for Algorithm L (Lexicographic combinations) in Section 7.2.1.3 of The Art of Computer Programming, Volume 4A: Combinatorial Algorithms, Part 1 :
internal class CombinationsWithoutRepetition<T> : IEnumerator<T[]> internal class CombinationsWithoutRepetition<T> : IEnumerator<T[]>
{ {
private bool _firstElement;
private int[] _pointers; private int[] _pointers;
private T[] _nElements; private T[] _nElements;
private readonly int _p; private readonly int _p;
public T[] Current { get; private set; }
object IEnumerator.Current => Current;
public CombinationsWithoutRepetition(T[] nElements, int p) public CombinationsWithoutRepetition(T[] nElements, int p)
{ {
@ -26,7 +25,8 @@ namespace CodeGenerator.HttpUtilities
ResetCurrent(); ResetCurrent();
} }
private bool _firstElement; public T[] Current { get; private set; }
object IEnumerator.Current => Current;
public bool MoveNext() public bool MoveNext()
{ {

View File

@ -1,4 +1,4 @@
// 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;
@ -7,7 +7,7 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
namespace CodeGenerator.HttpUtilities namespace CodeGenerator.HttpUtilities
{ {
@ -66,9 +66,9 @@ namespace CodeGenerator.HttpUtilities
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{{ {{
public static partial class HttpUtilities public static partial class HttpUtilities
{{ {{
@ -76,10 +76,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
{0} {0}
{1} {1}
private readonly static Tuple<ulong, ulong, HttpMethod, int>[] _knownMethods = private static readonly Tuple<ulong, ulong, HttpMethod, int>[] _knownMethods =
new Tuple<ulong, ulong, HttpMethod, int>[{2}]; new Tuple<ulong, ulong, HttpMethod, int>[{2}];
private readonly static string[] _methodNames = new string[{3}]; private static readonly string[] _methodNames = new string[{3}];
static HttpUtilities() static HttpUtilities()
{{ {{
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
var methodInfo = methodsInfo[index]; var methodInfo = methodsInfo[index];
var httpMethodFieldName = GetHttpMethodFieldName(methodInfo); var httpMethodFieldName = GetHttpMethodFieldName(methodInfo);
result.AppendFormat(" private readonly static ulong {0} = GetAsciiStringAsLong(\"{1}\");", httpMethodFieldName, methodInfo.MethodAsciiString.Replace("\0", "\\0")); result.AppendFormat(" private static readonly ulong {0} = GetAsciiStringAsLong(\"{1}\");", httpMethodFieldName, methodInfo.MethodAsciiString.Replace("\0", "\\0"));
if (index < methodsInfo.Count - 1) if (index < methodsInfo.Count - 1)
{ {
@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
var hexMaskString = HttpUtilitiesGeneratorHelpers.GeHexString(maskArray, "0x", ", "); var hexMaskString = HttpUtilitiesGeneratorHelpers.GeHexString(maskArray, "0x", ", ");
var maskFieldName = GetMaskFieldName(maskBytesLength); var maskFieldName = GetMaskFieldName(maskBytesLength);
result.AppendFormat(" private readonly static ulong {0} = GetMaskAsLong(new byte[]\r\n {{{1}}});", maskFieldName, hexMaskString); result.AppendFormat(" private static readonly ulong {0} = GetMaskAsLong(new byte[]\r\n {{{1}}});", maskFieldName, hexMaskString);
result.AppendLine(); result.AppendLine();
if (index < distinctLengths.Count - 1) if (index < distinctLengths.Count - 1)
{ {

View File

@ -1,4 +1,4 @@
// 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;