MemoryPoolIterator feedback

This commit is contained in:
Ben Adams 2016-11-21 22:18:17 +00:00
parent 9ec4d88fbe
commit 2eba4017c1
8 changed files with 33 additions and 17 deletions

View File

@ -1,3 +1,3 @@
{ {
"projects": [ "src" ] "projects": ["src"]
} }

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
{ {
public abstract partial class Frame : IFrameControl public abstract partial class Frame : IFrameControl
{ {
// byte consts don't have a data type annotation so we pre-cast them // byte types don't have a data type annotation so we pre-cast them; to avoid in-place casts
private const byte ByteCR = (byte)'\r'; private const byte ByteCR = (byte)'\r';
private const byte ByteLF = (byte)'\n'; private const byte ByteLF = (byte)'\n';
private const byte ByteColon = (byte)':'; private const byte ByteColon = (byte)':';

View File

@ -774,10 +774,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int LocateFirstFoundByte(Vector<byte> byteEquals) internal static int LocateFirstFoundByte(Vector<byte> byteEquals)
{ {
var vector64 = Vector.AsVectorInt64(byteEquals); var vector64 = Vector.AsVectorUInt64(byteEquals);
long longValue = 0; ulong longValue = 0;
var i = 0; var i = 0;
for (; i < Vector<long>.Count; i++) // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
for (; i < Vector<ulong>.Count; i++)
{ {
longValue = vector64[i]; longValue = vector64[i];
if (longValue == 0) continue; if (longValue == 0) continue;
@ -785,7 +786,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
// Flag least significant power of two bit // Flag least significant power of two bit
var powerOfTwoFlag = (ulong)(longValue ^ (longValue - 1)); var powerOfTwoFlag = (longValue ^ (longValue - 1));
// Shift all powers of two into the high byte and extract // Shift all powers of two into the high byte and extract
var foundByteIndex = (int)((powerOfTwoFlag * _xorPowerOfTwoToHighByte) >> 57); var foundByteIndex = (int)((powerOfTwoFlag * _xorPowerOfTwoToHighByte) >> 57);
// Single LEA instruction with jitted const (using function result) // Single LEA instruction with jitted const (using function result)
@ -803,7 +804,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
var block = _block; var block = _block;
if (block == null) if (block == null)
{ {
return false; ThrowInvalidOperationException_PutPassedEndOfBlock();
} }
var index = _index; var index = _index;
@ -817,7 +818,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return true; return true;
} }
return wasLastBlock ? false : PutMultiBlock(data); if (wasLastBlock)
{
ThrowInvalidOperationException_PutPassedEndOfBlock();
}
return PutMultiBlock(data);
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
@ -841,6 +847,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
} }
if (wasLastBlock) if (wasLastBlock)
{ {
ThrowInvalidOperationException_PutPassedEndOfBlock();
return false; return false;
} }
} while (true); } while (true);
@ -848,13 +855,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return true; return true;
} }
private static void ThrowInvalidOperationException_PutPassedEndOfBlock()
{
throw new InvalidOperationException("Attempted to put passed end of block.");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetLength(MemoryPoolIterator end) public int GetLength(MemoryPoolIterator end)
{ {
var block = _block; var block = _block;
if (block == null || end.IsDefault) if (block == null || end.IsDefault)
{ {
return -1; ThrowInvalidOperationException_GetLengthNullBlock();
} }
if (block == end._block) if (block == end._block)
@ -865,6 +877,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
return GetLengthMultiBlock(ref end); return GetLengthMultiBlock(ref end);
} }
private static void ThrowInvalidOperationException_GetLengthNullBlock()
{
throw new InvalidOperationException("Attempted GetLength of non existent block.");
}
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
public int GetLengthMultiBlock(ref MemoryPoolIterator end) public int GetLengthMultiBlock(ref MemoryPoolIterator end)
{ {
@ -1234,7 +1251,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
// Vector<byte> .ctor doesn't become an intrinsic due to detection issue // Vector<byte> .ctor doesn't become an intrinsic due to detection issue
// However this does cause it to become an intrinsic (with additional multiply and reg->reg copy) // However this does cause it to become an intrinsic (with additional multiply and reg->reg copy)
// https://github.com/dotnet/coreclr/issues/7459#issuecomment-253965670 // https://github.com/dotnet/coreclr/issues/7459#issuecomment-253965670
return Vector.AsVectorByte(new Vector<ulong>(vectorByte * 0x0101010101010101ul)); return Vector.AsVectorByte(new Vector<uint>(vectorByte * 0x01010101u));
} }
} }

View File

@ -8,7 +8,6 @@ using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using RequestLineStatus = Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.RequestLineStatus; using RequestLineStatus = Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame.RequestLineStatus;

View File

@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
} }
// Can't put anything by the end // Can't put anything by the end
Assert.False(head.Put(0xFF)); Assert.ThrowsAny<InvalidOperationException>(() => head.Put(0xFF));
for (var i = 0; i < 4; ++i) for (var i = 0; i < 4; ++i)
{ {
@ -979,7 +979,6 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
var end = default(MemoryPoolIterator); var end = default(MemoryPoolIterator);
Assert.False(default(MemoryPoolIterator).TryPeekLong(out longValue)); Assert.False(default(MemoryPoolIterator).TryPeekLong(out longValue));
Assert.False(default(MemoryPoolIterator).Put(byteCr));
Assert.Null(default(MemoryPoolIterator).GetAsciiString(ref end)); Assert.Null(default(MemoryPoolIterator).GetAsciiString(ref end));
Assert.Null(default(MemoryPoolIterator).GetUtf8String(ref end)); Assert.Null(default(MemoryPoolIterator).GetUtf8String(ref end));
// Assert.Equal doesn't work for default(ArraySegments) // Assert.Equal doesn't work for default(ArraySegments)
@ -995,7 +994,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
default(MemoryPoolIterator).CopyFrom(default(ArraySegment<byte>)); default(MemoryPoolIterator).CopyFrom(default(ArraySegment<byte>));
default(MemoryPoolIterator).CopyFromAscii(""); default(MemoryPoolIterator).CopyFromAscii("");
Assert.Equal(default(MemoryPoolIterator).GetLength(end), -1); Assert.ThrowsAny<InvalidOperationException>(() => default(MemoryPoolIterator).Put(byteCr));
Assert.ThrowsAny<InvalidOperationException>(() => default(MemoryPoolIterator).GetLength(end));
Assert.ThrowsAny<InvalidOperationException>(() => default(MemoryPoolIterator).Skip(1)); Assert.ThrowsAny<InvalidOperationException>(() => default(MemoryPoolIterator).Skip(1));
} }

View File

@ -10,11 +10,11 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel; using Microsoft.AspNetCore.Server.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Moq; using Moq;
using Xunit; using Xunit;
using Xunit.Sdk; using Xunit.Sdk;
using Microsoft.AspNetCore.Testing;
namespace Microsoft.AspNetCore.Server.KestrelTests namespace Microsoft.AspNetCore.Server.KestrelTests
{ {

View File

@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Server.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers namespace Microsoft.AspNetCore.Testing
{ {
public class MockConnection : Connection, IDisposable public class MockConnection : Connection, IDisposable
{ {

View File

@ -4,7 +4,7 @@
using System; using System;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers namespace Microsoft.AspNetCore.Testing
{ {
public static class SocketInputExtensions public static class SocketInputExtensions
{ {