better GetKnownMethodIndex, unit tests, benchmark repair
This commit is contained in:
parent
b89415d9b2
commit
96fead6282
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
||||||
SetKnownMethod(_mask7Chars, _httpDeleteMethodLong, HttpMethod.Delete, 6);
|
SetKnownMethod(_mask7Chars, _httpDeleteMethodLong, HttpMethod.Delete, 6);
|
||||||
SetKnownMethod(_mask8Chars, _httpConnectMethodLong, HttpMethod.Connect, 7);
|
SetKnownMethod(_mask8Chars, _httpConnectMethodLong, HttpMethod.Connect, 7);
|
||||||
SetKnownMethod(_mask8Chars, _httpOptionsMethodLong, HttpMethod.Options, 7);
|
SetKnownMethod(_mask8Chars, _httpOptionsMethodLong, HttpMethod.Options, 7);
|
||||||
FillEmptyKnownMethods();
|
FillKnownMethodsGaps();
|
||||||
_methodNames[(byte)HttpMethod.Get] = HttpMethods.Get;
|
_methodNames[(byte)HttpMethod.Get] = HttpMethods.Get;
|
||||||
_methodNames[(byte)HttpMethod.Put] = HttpMethods.Put;
|
_methodNames[(byte)HttpMethod.Put] = HttpMethods.Put;
|
||||||
_methodNames[(byte)HttpMethod.Delete] = HttpMethods.Delete;
|
_methodNames[(byte)HttpMethod.Delete] = HttpMethods.Delete;
|
||||||
|
|
@ -64,9 +64,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static int GetKnownMethodIndex(ulong value)
|
private static int GetKnownMethodIndex(ulong value)
|
||||||
{
|
{
|
||||||
var tmp = (int)value & 0x100604;
|
const int MagicNumer = 0x0600000C;
|
||||||
|
var tmp = (int)value & MagicNumer;
|
||||||
|
|
||||||
return ((tmp >> 2) | (tmp >> 8) | (tmp >> 17)) & 0x0F;
|
return ((tmp >> 2) | (tmp >> 23)) & 0x0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
@ -75,15 +76,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
|
||||||
_knownMethods[GetKnownMethodIndex(knownMethodUlong)] = new Tuple<ulong, ulong, HttpMethod, int, bool>(mask, knownMethodUlong, knownMethod, length, true);
|
_knownMethods[GetKnownMethodIndex(knownMethodUlong)] = new Tuple<ulong, ulong, HttpMethod, int, bool>(mask, knownMethodUlong, knownMethod, length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FillEmptyKnownMethods()
|
|
||||||
|
private static void FillKnownMethodsGaps()
|
||||||
{
|
{
|
||||||
var knownMethods = _knownMethods;
|
var knownMethods = _knownMethods;
|
||||||
var length = knownMethods.Length;
|
var length = knownMethods.Length;
|
||||||
|
var invalidHttpMethod = new Tuple<ulong, ulong, HttpMethod, int, bool>(_mask8Chars, 0ul, HttpMethod.Custom, 0, false);
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
if (knownMethods[i] == null)
|
if (knownMethods[i] == null)
|
||||||
{
|
{
|
||||||
knownMethods[i] = new Tuple<ulong, ulong, HttpMethod, int, bool>(_mask8Chars, 0ul, HttpMethod.Custom, 0, false);
|
knownMethods[i] = invalidHttpMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
{
|
{
|
||||||
public class KnownStrings
|
public class KnownStrings
|
||||||
{
|
{
|
||||||
static byte[] _methodGet = Encoding.UTF8.GetBytes("GET ");
|
static byte[] _methodConnect = Encoding.ASCII.GetBytes("CONNECT ");
|
||||||
static byte[] _methodConnect = Encoding.UTF8.GetBytes("CONNECT ");
|
static byte[] _methodDelete = Encoding.ASCII.GetBytes("DELETE \0");
|
||||||
static byte[] _methodDelete = Encoding.UTF8.GetBytes("DELETE ");
|
static byte[] _methodGet = Encoding.ASCII.GetBytes("GET ");
|
||||||
static byte[] _methodHead = Encoding.UTF8.GetBytes("HEAD ");
|
static byte[] _methodHead = Encoding.ASCII.GetBytes("HEAD \0\0\0");
|
||||||
static byte[] _methodPatch = Encoding.UTF8.GetBytes("PATCH ");
|
static byte[] _methodPatch = Encoding.ASCII.GetBytes("PATCH \0\0");
|
||||||
static byte[] _methodPost = Encoding.UTF8.GetBytes("POST ");
|
static byte[] _methodPost = Encoding.ASCII.GetBytes("POST \0\0\0");
|
||||||
static byte[] _methodPut = Encoding.UTF8.GetBytes("PUT ");
|
static byte[] _methodPut = Encoding.ASCII.GetBytes("PUT \0\0\0\0");
|
||||||
static byte[] _methodOptions = Encoding.UTF8.GetBytes("OPTIONS ");
|
static byte[] _methodOptions = Encoding.ASCII.GetBytes("OPTIONS ");
|
||||||
static byte[] _methodTrace = Encoding.UTF8.GetBytes("TRACE ");
|
static byte[] _methodTrace = Encoding.ASCII.GetBytes("TRACE \0\0");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
|
{
|
||||||
|
public class KnownStringsTests
|
||||||
|
{
|
||||||
|
static byte[] _methodConnect = Encoding.ASCII.GetBytes("CONNECT ");
|
||||||
|
static byte[] _methodDelete = Encoding.ASCII.GetBytes("DELETE \0");
|
||||||
|
static byte[] _methodGet = Encoding.ASCII.GetBytes("GET ");
|
||||||
|
static byte[] _methodHead = Encoding.ASCII.GetBytes("HEAD \0\0\0");
|
||||||
|
static byte[] _methodPatch = Encoding.ASCII.GetBytes("PATCH \0\0");
|
||||||
|
static byte[] _methodPost = Encoding.ASCII.GetBytes("POST \0\0\0");
|
||||||
|
static byte[] _methodPut = Encoding.ASCII.GetBytes("PUT \0\0\0\0");
|
||||||
|
static byte[] _methodOptions = Encoding.ASCII.GetBytes("OPTIONS ");
|
||||||
|
static byte[] _methodTrace = Encoding.ASCII.GetBytes("TRACE \0\0");
|
||||||
|
|
||||||
|
|
||||||
|
const int MagicNumer = 0x0600000C;
|
||||||
|
static byte[] _invalidMethod1 = BitConverter.GetBytes((ulong)MagicNumer);
|
||||||
|
static byte[] _invalidMethod2 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
static byte[] _invalidMethod3 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
static byte[] _invalidMethod4 = Encoding.ASCII.GetBytes("CONNECT ");
|
||||||
|
static byte[] _invalidMethod5 = Encoding.ASCII.GetBytes("DELETE \0");
|
||||||
|
static byte[] _invalidMethod6 = Encoding.ASCII.GetBytes("GET ");
|
||||||
|
static byte[] _invalidMethod7 = Encoding.ASCII.GetBytes("HEAD \0\0\0");
|
||||||
|
static byte[] _invalidMethod8 = Encoding.ASCII.GetBytes("PATCH \0\0");
|
||||||
|
static byte[] _invalidMethod9 = Encoding.ASCII.GetBytes("POST \0\0\0");
|
||||||
|
static byte[] _invalidMethod10 = Encoding.ASCII.GetBytes("PUT \0\0\0\0");
|
||||||
|
static byte[] _invalidMethod11 = Encoding.ASCII.GetBytes("OPTIONS ");
|
||||||
|
static byte[] _invalidMethod12 = Encoding.ASCII.GetBytes("TRACE \0\0");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static object[] CreateTestDataEntry(byte[] methodData, HttpMethod expectedMethod, int expectedLength, bool expectedResult)
|
||||||
|
{
|
||||||
|
return new object[] { methodData, expectedMethod, expectedLength, expectedResult };
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly List<object[]> _testData
|
||||||
|
= new List<object[]>
|
||||||
|
{
|
||||||
|
CreateTestDataEntry(_methodGet, HttpMethod.Get, 3,true),
|
||||||
|
CreateTestDataEntry(_methodPut, HttpMethod.Put, 3,true),
|
||||||
|
CreateTestDataEntry(_methodPost, HttpMethod.Post, 4,true),
|
||||||
|
CreateTestDataEntry(_methodHead, HttpMethod.Head, 4,true),
|
||||||
|
CreateTestDataEntry(_methodTrace, HttpMethod.Trace, 5,true),
|
||||||
|
CreateTestDataEntry(_methodPatch, HttpMethod.Patch, 5,true),
|
||||||
|
CreateTestDataEntry(_methodDelete, HttpMethod.Delete, 6,true),
|
||||||
|
CreateTestDataEntry(_methodConnect, HttpMethod.Connect, 7,true),
|
||||||
|
CreateTestDataEntry(_methodOptions, HttpMethod.Options, 7,true),
|
||||||
|
CreateTestDataEntry(_invalidMethod1, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod2, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod3, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod4, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod5, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod6, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod7, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod8, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod9, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod10, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod11, HttpMethod.Custom, 0,false),
|
||||||
|
CreateTestDataEntry(_invalidMethod12, HttpMethod.Custom, 0,false),
|
||||||
|
};
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> TestData => _testData;
|
||||||
|
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(TestData), MemberType = typeof(KnownStringsTests))]
|
||||||
|
public void GetsKnownMethod(byte[] methodData, HttpMethod expectedMethod, int expectedLength, bool expectedResult)
|
||||||
|
{
|
||||||
|
var data = new Span<byte>(methodData);
|
||||||
|
|
||||||
|
HttpMethod method;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
bool result = data.GetKnownMethod(out method, out length);
|
||||||
|
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
Assert.Equal(expectedMethod, method);
|
||||||
|
Assert.Equal(expectedLength, length);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue