React to pipeline changes (#2234)

React to pipeline changes
This commit is contained in:
Pavel Krymets 2018-01-04 09:54:42 -08:00 committed by GitHub
parent b57ac72431
commit 1fa001e7db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 187 additions and 143 deletions

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
private const int InnerLoopCount = 512; private const int InnerLoopCount = 512;
public ReadableBuffer _buffer; public ReadOnlyBuffer _buffer;
public Http1Connection _http1Connection; public Http1Connection _http1Connection;
[IterationSetup] [IterationSetup]

View File

@ -2,6 +2,7 @@
// 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.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
private readonly HttpParser<Adapter> _parser = new HttpParser<Adapter>(); private readonly HttpParser<Adapter> _parser = new HttpParser<Adapter>();
private ReadableBuffer _buffer; private ReadOnlyBuffer _buffer;
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)] [Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]
public void PlaintextTechEmpower() public void PlaintextTechEmpower()
@ -46,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
private void InsertData(byte[] data) private void InsertData(byte[] data)
{ {
_buffer = ReadableBuffer.Create(data); _buffer = new ReadOnlyBuffer(data);
} }
private void ParseData() private void ParseData()

View File

@ -2,6 +2,8 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
@ -21,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public static readonly NullParser<Http1ParsingHandler> Instance = new NullParser<Http1ParsingHandler>(); public static readonly NullParser<Http1ParsingHandler> Instance = new NullParser<Http1ParsingHandler>();
public bool ParseHeaders(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) public bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes)
{ {
handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue)); handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue)); handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
@ -34,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
return true; return true;
} }
public bool ParseRequestLine(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) public bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
handler.OnStartLine(HttpMethod.Get, handler.OnStartLine(HttpMethod.Get,
HttpVersion.Http11, HttpVersion.Http11,

View File

@ -25,20 +25,21 @@
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsLoggingTestingPackageVersion> <MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview1-27965</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion> <MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview1-26016-05</MicrosoftNETCoreApp21PackageVersion> <MicrosoftNETCoreApp21PackageVersion>2.1.0-preview1-26102-01</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview1-27965</MicrosoftNetHttpHeadersPackageVersion> <MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview1-27965</MicrosoftNetHttpHeadersPackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion> <MicrosoftNETTestSdkPackageVersion>15.3.0</MicrosoftNETTestSdkPackageVersion>
<MoqPackageVersion>4.7.49</MoqPackageVersion> <MoqPackageVersion>4.7.49</MoqPackageVersion>
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion> <NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
<SystemBuffersPackageVersion>4.5.0-preview1-26016-05</SystemBuffersPackageVersion> <SystemBuffersPackageVersion>4.5.0-preview1-26102-01</SystemBuffersPackageVersion>
<SystemIOPipelinesPackageVersion>0.1.0-e171215-1</SystemIOPipelinesPackageVersion> <SystemBuffersPrimitivesPackageVersion>0.1.0-e180104-2</SystemBuffersPrimitivesPackageVersion>
<SystemIOPipelinesTestingPackageVersion>0.1.0-e171215-1</SystemIOPipelinesTestingPackageVersion> <SystemIOPipelinesPackageVersion>0.1.0-e180104-2</SystemIOPipelinesPackageVersion>
<SystemMemoryPackageVersion>4.5.0-preview1-26016-05</SystemMemoryPackageVersion> <SystemIOPipelinesTestingPackageVersion>0.1.0-e180104-2</SystemIOPipelinesTestingPackageVersion>
<SystemNumericsVectorsPackageVersion>4.5.0-preview1-26016-05</SystemNumericsVectorsPackageVersion> <SystemMemoryPackageVersion>4.5.0-preview1-26102-01</SystemMemoryPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-26016-05</SystemRuntimeCompilerServicesUnsafePackageVersion> <SystemNumericsVectorsPackageVersion>4.5.0-preview1-26102-01</SystemNumericsVectorsPackageVersion>
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview1-26016-05</SystemSecurityCryptographyCngPackageVersion> <SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-26102-01</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e171215-1</SystemTextEncodingsWebUtf8PackageVersion> <SystemSecurityCryptographyCngPackageVersion>4.5.0-preview1-26102-01</SystemSecurityCryptographyCngPackageVersion>
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview2-25707-02</SystemThreadingTasksExtensionsPackageVersion> <SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e180104-2</SystemTextEncodingsWebUtf8PackageVersion>
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview1-26102-01</SystemThreadingTasksExtensionsPackageVersion>
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion> <XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion> <XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.3.1</XunitRunnerVisualStudioPackageVersion> <XunitRunnerVisualStudioPackageVersion>2.3.1</XunitRunnerVisualStudioPackageVersion>

View File

@ -6,6 +6,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
{ {

View File

@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
// Internal for testing // Internal for testing
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, IScheduler writerScheduler) => new PipeOptions internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, Scheduler writerScheduler) => new PipeOptions
( (
pool: memoryPool, pool: memoryPool,
readerScheduler: serviceContext.ThreadPool, readerScheduler: serviceContext.ThreadPool,
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0 maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
); );
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, IScheduler readerScheduler) => new PipeOptions internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, MemoryPool memoryPool, Scheduler readerScheduler) => new PipeOptions
( (
pool: memoryPool, pool: memoryPool,
readerScheduler: readerScheduler, readerScheduler: readerScheduler,

View File

@ -2,11 +2,14 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.Diagnostics; using System.Diagnostics;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Text.Encodings.Web.Utf8; using System.Text.Encodings.Web.Utf8;
using System.Threading;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
@ -66,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
Input.CancelPendingRead(); Input.CancelPendingRead();
} }
public void ParseRequest(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) public void ParseRequest(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
consumed = buffer.Start; consumed = buffer.Start;
examined = buffer.End; examined = buffer.End;
@ -104,7 +107,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
} }
public bool TakeStartLine(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) public bool TakeStartLine(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
var overLength = false; var overLength = false;
if (buffer.Length >= ServerOptions.Limits.MaxRequestLineSize) if (buffer.Length >= ServerOptions.Limits.MaxRequestLineSize)
@ -122,7 +125,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return result; return result;
} }
public bool TakeMessageHeaders(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) public bool TakeMessageHeaders(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
// Make sure the buffer is limited // Make sure the buffer is limited
bool overLength = false; bool overLength = false;
@ -424,7 +427,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest); TimeoutControl.SetTimeout(_keepAliveTicks, TimeoutAction.StopProcessingNextRequest);
} }
protected override bool BeginRead(out ReadableBufferAwaitable awaitable) protected override bool BeginRead(out ValueAwaiter<ReadResult> awaitable)
{ {
awaitable = Input.ReadAsync(); awaitable = Input.ReadAsync();
return true; return true;

View File

@ -2,6 +2,8 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.IO; using System.IO;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -149,7 +151,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
} }
protected void Copy(ReadableBuffer readableBuffer, WritableBuffer writableBuffer) protected void Copy(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer)
{ {
_context.TimeoutControl.BytesRead(readableBuffer.Length); _context.TimeoutControl.BytesRead(readableBuffer.Length);
@ -171,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_pumpTask = PumpAsync(); _pumpTask = PumpAsync();
} }
protected virtual bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined) protected virtual bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -296,7 +298,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
RequestUpgrade = true; RequestUpgrade = true;
} }
protected override bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined) protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
{ {
Copy(readableBuffer, writableBuffer); Copy(readableBuffer, writableBuffer);
consumed = readableBuffer.End; consumed = readableBuffer.End;
@ -318,7 +320,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_inputLength = _contentLength; _inputLength = _contentLength;
} }
protected override bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined) protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
{ {
if (_inputLength == 0) if (_inputLength == 0)
{ {
@ -366,10 +368,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
RequestKeepAlive = keepAlive; RequestKeepAlive = keepAlive;
} }
protected override bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined) protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
{ {
consumed = default(ReadCursor); consumed = default(Position);
examined = default(ReadCursor); examined = default(Position);
while (_mode < Mode.Trailer) while (_mode < Mode.Trailer)
{ {
@ -457,17 +459,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
} }
private void ParseChunkedPrefix(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) private void ParseChunkedPrefix(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
consumed = buffer.Start; consumed = buffer.Start;
examined = buffer.Start; examined = buffer.Start;
var reader = new ReadableBufferReader(buffer); var reader = BufferReader.Create(buffer);
var ch1 = reader.Take(); var ch1 = reader.Take();
var ch2 = reader.Take(); var ch2 = reader.Take();
if (ch1 == -1 || ch2 == -1) if (ch1 == -1 || ch2 == -1)
{ {
examined = reader.Cursor; examined = reader.Position;
return; return;
} }
@ -478,8 +480,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
if (ch1 == ';') if (ch1 == ';')
{ {
consumed = reader.Cursor; consumed = reader.Position;
examined = reader.Cursor; examined = reader.Position;
AddAndCheckConsumedBytes(reader.ConsumedBytes); AddAndCheckConsumedBytes(reader.ConsumedBytes);
_inputLength = chunkSize; _inputLength = chunkSize;
@ -490,14 +492,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
ch2 = reader.Take(); ch2 = reader.Take();
if (ch2 == -1) if (ch2 == -1)
{ {
examined = reader.Cursor; examined = reader.Position;
return; return;
} }
if (ch1 == '\r' && ch2 == '\n') if (ch1 == '\r' && ch2 == '\n')
{ {
consumed = reader.Cursor; consumed = reader.Position;
examined = reader.Cursor; examined = reader.Position;
AddAndCheckConsumedBytes(reader.ConsumedBytes); AddAndCheckConsumedBytes(reader.ConsumedBytes);
_inputLength = chunkSize; _inputLength = chunkSize;
@ -513,7 +515,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_context.ThrowRequestRejected(RequestRejectionReason.BadChunkSizeData); _context.ThrowRequestRejected(RequestRejectionReason.BadChunkSizeData);
} }
private void ParseExtension(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) private void ParseExtension(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
// Chunk-extensions not currently parsed // Chunk-extensions not currently parsed
// Just drain the data // Just drain the data
@ -522,8 +524,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
do do
{ {
ReadCursor extensionCursor; Position extensionCursor;
if (ReadCursorOperations.Seek(buffer.Start, buffer.End, out extensionCursor, ByteCR) == -1) if (ReadOnlyBuffer.Seek(buffer.Start, buffer.End, out extensionCursor, ByteCR) == -1)
{ {
// End marker not found yet // End marker not found yet
consumed = buffer.End; consumed = buffer.End;
@ -565,7 +567,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} while (_mode == Mode.Extension); } while (_mode == Mode.Extension);
} }
private void ReadChunkedData(ReadableBuffer buffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined) private void ReadChunkedData(ReadOnlyBuffer buffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
{ {
var actual = Math.Min(buffer.Length, _inputLength); var actual = Math.Min(buffer.Length, _inputLength);
consumed = buffer.Move(buffer.Start, actual); consumed = buffer.Move(buffer.Start, actual);
@ -582,7 +584,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
} }
private void ParseChunkedSuffix(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) private void ParseChunkedSuffix(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
consumed = buffer.Start; consumed = buffer.Start;
examined = buffer.Start; examined = buffer.Start;
@ -608,7 +610,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
} }
private void ParseChunkedTrailer(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) private void ParseChunkedTrailer(ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
consumed = buffer.Start; consumed = buffer.Start;
examined = buffer.Start; examined = buffer.Start;

View File

@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken); return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
} }
private async Task FlushAsyncAwaited(WritableBufferAwaitable awaitable, long count, CancellationToken cancellationToken) private async Task FlushAsyncAwaited(ValueAwaiter<FlushResult> awaitable, long count, CancellationToken cancellationToken)
{ {
// https://github.com/dotnet/corefxlab/issues/1334 // https://github.com/dotnet/corefxlab/issues/1334
// Since the flush awaitable doesn't currently support multiple awaiters // Since the flush awaitable doesn't currently support multiple awaiters

View File

@ -2,6 +2,8 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -31,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private const byte ByteQuestionMark = (byte)'?'; private const byte ByteQuestionMark = (byte)'?';
private const byte BytePercentage = (byte)'%'; private const byte BytePercentage = (byte)'%';
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) public unsafe bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined)
{ {
consumed = buffer.Start; consumed = buffer.Start;
examined = buffer.End; examined = buffer.End;
@ -186,7 +188,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
handler.OnStartLine(method, httpVersion, targetBuffer, pathBuffer, query, customMethod, pathEncoded); handler.OnStartLine(method, httpVersion, targetBuffer, pathBuffer, query, customMethod, pathEncoded);
} }
public unsafe bool ParseHeaders(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) public unsafe bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes)
{ {
consumed = buffer.Start; consumed = buffer.Start;
examined = buffer.End; examined = buffer.End;
@ -194,8 +196,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
var bufferEnd = buffer.End; var bufferEnd = buffer.End;
var reader = new ReadableBufferReader(buffer); var reader = BufferReader.Create(buffer);
var start = default(ReadableBufferReader); var start = default(BufferReader<ReadOnlyBuffer>);
var done = false; var done = false;
try try
@ -276,10 +278,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
else else
{ {
var current = reader.Cursor; var current = reader.Position;
// Split buffers // Split buffers
if (ReadCursorOperations.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1) if (ReadOnlyBuffer.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1)
{ {
// Not there // Not there
return false; return false;
@ -312,7 +314,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
finally finally
{ {
consumed = reader.Cursor; consumed = reader.Position;
consumedBytes = reader.ConsumedBytes; consumedBytes = reader.ConsumedBytes;
if (done) if (done)
@ -412,10 +414,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private static bool TryGetNewLine(ref ReadableBuffer buffer, out ReadCursor found) private static bool TryGetNewLine(ref ReadOnlyBuffer buffer, out Position found)
{ {
var start = buffer.Start; var start = buffer.Start;
if (ReadCursorOperations.Seek(start, buffer.End, out found, ByteLF) != -1) if (ReadOnlyBuffer.Seek(start, buffer.End, out found, ByteLF) != -1)
{ {
// Move 1 byte past the \n // Move 1 byte past the \n
found = buffer.Move(found, 1); found = buffer.Move(found, 1);

View File

@ -380,7 +380,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
} }
protected virtual bool BeginRead(out ReadableBufferAwaitable awaitable) protected virtual bool BeginRead(out ValueAwaiter<ReadResult> awaitable)
{ {
awaitable = default; awaitable = default;
return false; return false;
@ -1302,7 +1302,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
( (
pool: _context.MemoryPool, pool: _context.MemoryPool,
readerScheduler: ServiceContext.ThreadPool, readerScheduler: ServiceContext.ThreadPool,
writerScheduler: InlineScheduler.Default, writerScheduler: Scheduler.Inline,
maximumSizeHigh: 1, maximumSizeHigh: 1,
maximumSizeLow: 1 maximumSizeLow: 1
)); ));

View File

@ -1,14 +1,16 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.IO.Pipelines; using System.IO.Pipelines;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
public interface IHttpParser<TRequestHandler> where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler public interface IHttpParser<TRequestHandler> where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler
{ {
bool ParseRequestLine(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined); bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined);
bool ParseHeaders(TRequestHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes); bool ParseHeaders(TRequestHandler handler, ReadOnlyBuffer buffer, out Position consumed, out Position examined, out int consumedBytes);
} }
} }

View File

@ -2,6 +2,7 @@
// 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.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private static byte[] _numericBytesScratch; private static byte[] _numericBytesScratch;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> ToSpan(this ReadableBuffer buffer) public static ReadOnlySpan<byte> ToSpan(this ReadOnlyBuffer buffer)
{ {
if (buffer.IsSingleSpan) if (buffer.IsSingleSpan)
{ {
@ -35,6 +36,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return result; return result;
} }
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)
{
if (!MemoryMarshal.TryGetArray(memory, out var result))
{
throw new InvalidOperationException("Buffer backed by array was expected");
}
return result;
}
public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data) public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data)
{ {
if (string.IsNullOrEmpty(data)) if (string.IsNullOrEmpty(data))

View File

@ -2,6 +2,8 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Text; using System.Text;
@ -214,7 +216,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
} }
} }
private bool ParsePreface(ReadableBuffer readableBuffer, out ReadCursor consumed, out ReadCursor examined) private bool ParsePreface(ReadOnlyBuffer readableBuffer, out Position consumed, out Position examined)
{ {
consumed = readableBuffer.Start; consumed = readableBuffer.Start;
examined = readableBuffer.End; examined = readableBuffer.End;

View File

@ -1,13 +1,15 @@
// 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.Buffers;
using System.Collections.Sequences;
using System.IO.Pipelines; using System.IO.Pipelines;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
{ {
public static class Http2FrameReader public static class Http2FrameReader
{ {
public static bool ReadFrame(ReadableBuffer readableBuffer, Http2Frame frame, out ReadCursor consumed, out ReadCursor examined) public static bool ReadFrame(ReadOnlyBuffer readableBuffer, Http2Frame frame, out Position consumed, out Position examined)
{ {
consumed = readableBuffer.Start; consumed = readableBuffer.Start;
examined = readableBuffer.End; examined = readableBuffer.End;

View File

@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
( (
pool: MemoryPool, pool: MemoryPool,
readerScheduler: _context.ServiceContext.ThreadPool, readerScheduler: _context.ServiceContext.ThreadPool,
writerScheduler: InlineScheduler.Default, writerScheduler: Scheduler.Inline,
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0, maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0 maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
); );
@ -81,8 +81,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
( (
pool: MemoryPool, pool: MemoryPool,
readerScheduler: InlineScheduler.Default, readerScheduler: Scheduler.Inline,
writerScheduler: InlineScheduler.Default, writerScheduler: Scheduler.Inline,
maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0, maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0 maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
); );

View File

@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
public class InlineLoggingThreadPool : IThreadPool public class InlineLoggingThreadPool : KestrelThreadPool
{ {
private readonly IKestrelTrace _log; private readonly IKestrelTrace _log;
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
_log = log; _log = log;
} }
public void Run(Action action) public override void Run(Action action)
{ {
try try
{ {
@ -28,12 +28,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
public void UnsafeRun(WaitCallback action, object state) public override void UnsafeRun(WaitCallback action, object state)
{ {
action(state); action(state);
} }
public void Schedule(Action<object> action, object state) public override void Schedule(Action action)
{
Run(action);
}
public override void Schedule(Action<object> action, object state)
{ {
try try
{ {

View File

@ -7,9 +7,9 @@ using System.Threading;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
public interface IThreadPool : IScheduler public abstract class KestrelThreadPool: Scheduler
{ {
void Run(Action action); public abstract void Run(Action action);
void UnsafeRun(WaitCallback action, object state); public abstract void UnsafeRun(WaitCallback action, object state);
} }
} }

View File

@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
public class LoggingThreadPool : IThreadPool public class LoggingThreadPool : KestrelThreadPool
{ {
private readonly IKestrelTrace _log; private readonly IKestrelTrace _log;
@ -40,17 +40,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
}; };
} }
public void Run(Action action) public override void Run(Action action)
{ {
ThreadPool.QueueUserWorkItem(_runAction, action); ThreadPool.QueueUserWorkItem(_runAction, action);
} }
public void UnsafeRun(WaitCallback action, object state) public override void UnsafeRun(WaitCallback action, object state)
{ {
ThreadPool.QueueUserWorkItem(action, state); ThreadPool.QueueUserWorkItem(action, state);
} }
public void Schedule(Action<object> action, object state) public override void Schedule(Action action)
{
Run(action);
}
public override void Schedule(Action<object> action, object state)
{ {
Run(() => action(state)); Run(() => action(state));
} }

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
{ {
public IKestrelTrace Log { get; set; } public IKestrelTrace Log { get; set; }
public IThreadPool ThreadPool { get; set; } public KestrelThreadPool ThreadPool { get; set; }
public IHttpParser<Http1ParsingHandler> HttpParser { get; set; } public IHttpParser<Http1ParsingHandler> HttpParser { get; set; }

View File

@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
// TODO: This logic will eventually move into the IConnectionHandler<T> and off // TODO: This logic will eventually move into the IConnectionHandler<T> and off
// the service context once we get to https://github.com/aspnet/KestrelHttpServer/issues/1662 // the service context once we get to https://github.com/aspnet/KestrelHttpServer/issues/1662
IThreadPool threadPool = null; KestrelThreadPool threadPool = null;
switch (serverOptions.ApplicationSchedulingMode) switch (serverOptions.ApplicationSchedulingMode)
{ {
case SchedulingMode.Default: case SchedulingMode.Default:

View File

@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
public string ConnectionId { get; set; } public string ConnectionId { get; set; }
public virtual MemoryPool MemoryPool { get; } public virtual MemoryPool MemoryPool { get; }
public virtual IScheduler InputWriterScheduler { get; } public virtual Scheduler InputWriterScheduler { get; }
public virtual IScheduler OutputReaderScheduler { get; } public virtual Scheduler OutputReaderScheduler { get; }
public IPipeConnection Transport { get; set; } public IPipeConnection Transport { get; set; }
public IPipeConnection Application { get; set; } public IPipeConnection Application { get; set; }

View File

@ -6,6 +6,7 @@ using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Protocols;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
@ -183,7 +184,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
_bufferHandle.Dispose(); _bufferHandle.Dispose();
} }
private async Task ApplyBackpressureAsync(WritableBufferAwaitable flushTask) private async Task ApplyBackpressureAsync(ValueAwaiter<FlushResult> flushTask)
{ {
Log.ConnectionPause(ConnectionId); Log.ConnectionPause(ConnectionId);
_socket.ReadStop(); _socket.ReadStop();

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
public ListenerContext ListenerContext { get; set; } public ListenerContext ListenerContext { get; set; }
public override MemoryPool MemoryPool => ListenerContext.Thread.MemoryPool; public override MemoryPool MemoryPool => ListenerContext.Thread.MemoryPool;
public override IScheduler InputWriterScheduler => ListenerContext.Thread; public override Scheduler InputWriterScheduler => ListenerContext.Thread;
public override IScheduler OutputReaderScheduler => ListenerContext.Thread; public override Scheduler OutputReaderScheduler => ListenerContext.Thread;
} }
} }

View File

@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
{ {
public class LibuvThread : IScheduler public class LibuvThread : Scheduler
{ {
// maximum times the work queues swapped and are processed in a single pass // maximum times the work queues swapped and are processed in a single pass
// as completing a task may immediately have write data to put on the network // as completing a task may immediately have write data to put on the network
@ -390,7 +390,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
return await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task; return await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
} }
public void Schedule(Action<object> action, object state) public override void Schedule(Action action)
{
Post(state => state(), action);
}
public override void Schedule(Action<object> action, object state)
{ {
Post(action, state); Post(action, state);
} }

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
_bufs = handle + requestSize; _bufs = handle + requestSize;
} }
public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadableBuffer buffer) public LibuvAwaitable<UvWriteReq> WriteAsync(UvStreamHandle handle, ReadOnlyBuffer buffer)
{ {
Write(handle, buffer, LibuvAwaitable<UvWriteReq>.Callback, _awaitable); Write(handle, buffer, LibuvAwaitable<UvWriteReq>.Callback, _awaitable);
return _awaitable; return _awaitable;
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
private unsafe void Write( private unsafe void Write(
UvStreamHandle handle, UvStreamHandle handle,
ReadableBuffer buffer, ReadOnlyBuffer buffer,
Action<UvWriteReq, int, UvException, object> callback, Action<UvWriteReq, int, UvException, object> callback,
object state) object state)
{ {

View File

@ -2,15 +2,24 @@
// 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.InteropServices;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
{ {
public static class BufferExtensions public static class BufferExtensions
{ {
public static ArraySegment<byte> GetArray(this Memory<byte> buffer) public static ArraySegment<byte> GetArray(this Memory<byte> memory)
{ {
ArraySegment<byte> result; if (!memory.TryGetArray(out var result))
if (!buffer.TryGetArray(out result)) {
throw new InvalidOperationException("Buffer backed by array was expected");
}
return result;
}
public static ArraySegment<byte> GetArray(this ReadOnlyMemory<byte> memory)
{
if (!MemoryMarshal.TryGetArray(memory, out var result))
{ {
throw new InvalidOperationException("Buffer backed by array was expected"); throw new InvalidOperationException("Buffer backed by array was expected");
} }

View File

@ -52,8 +52,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
} }
public override MemoryPool MemoryPool { get; } public override MemoryPool MemoryPool { get; }
public override IScheduler InputWriterScheduler => InlineScheduler.Default; public override Scheduler InputWriterScheduler => Scheduler.Inline;
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default; public override Scheduler OutputReaderScheduler => Scheduler.TaskRun;
public async Task StartAsync(IConnectionHandler connectionHandler) public async Task StartAsync(IConnectionHandler connectionHandler)
{ {

View File

@ -2,10 +2,12 @@
// 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.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
{ {
@ -24,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
_eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError); _eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError);
} }
public SocketAwaitable SendAsync(ReadableBuffer buffers) public SocketAwaitable SendAsync(ReadOnlyBuffer buffers)
{ {
if (buffers.IsSingleSpan) if (buffers.IsSingleSpan)
{ {
@ -50,7 +52,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
return _awaitable; return _awaitable;
} }
private SocketAwaitable SendAsync(Memory<byte> buffer) private SocketAwaitable SendAsync(ReadOnlyMemory<byte> memory)
{ {
// The BufferList getter is much less expensive then the setter. // The BufferList getter is much less expensive then the setter.
if (_eventArgs.BufferList != null) if (_eventArgs.BufferList != null)
@ -59,9 +61,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
} }
#if NETCOREAPP2_1 #if NETCOREAPP2_1
_eventArgs.SetBuffer(buffer); _eventArgs.SetBuffer(MemoryMarshal.AsMemory(memory));
#else #else
var segment = buffer.GetArray(); var segment = memory.GetArray();
_eventArgs.SetBuffer(segment.Array, segment.Offset, segment.Count); _eventArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);
#endif #endif
@ -73,7 +75,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
return _awaitable; return _awaitable;
} }
private List<ArraySegment<byte>> GetBufferList(ReadableBuffer buffer) private List<ArraySegment<byte>> GetBufferList(ReadOnlyBuffer buffer)
{ {
Debug.Assert(!buffer.IsEmpty); Debug.Assert(!buffer.IsEmpty);
Debug.Assert(!buffer.IsSingleSpan); Debug.Assert(!buffer.IsSingleSpan);

View File

@ -12,8 +12,8 @@ namespace Microsoft.AspNetCore.Protocols.Features
IPipeConnection Application { get; set; } IPipeConnection Application { get; set; }
IScheduler InputWriterScheduler { get; } Scheduler InputWriterScheduler { get; }
IScheduler OutputReaderScheduler { get; } Scheduler OutputReaderScheduler { get; }
} }
} }

View File

@ -58,9 +58,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public IPipeConnection Transport { get; set; } public IPipeConnection Transport { get; set; }
public IPipeConnection Application { get; set; } public IPipeConnection Application { get; set; }
public IScheduler InputWriterScheduler => TaskRunScheduler.Default; public Scheduler InputWriterScheduler => Scheduler.TaskRun;
public IScheduler OutputReaderScheduler => TaskRunScheduler.Default; public Scheduler OutputReaderScheduler => Scheduler.TaskRun;
public string ConnectionId { get; set; } public string ConnectionId { get; set; }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Buffers; using System.Buffers;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Sequences;
using System.IO; using System.IO;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Linq; using System.Linq;
@ -33,8 +34,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private readonly ServiceContext _serviceContext; private readonly ServiceContext _serviceContext;
private readonly Http1ConnectionContext _http1ConnectionContext; private readonly Http1ConnectionContext _http1ConnectionContext;
private readonly MemoryPool _pipelineFactory; private readonly MemoryPool _pipelineFactory;
private ReadCursor _consumed; private Position _consumed;
private ReadCursor _examined; private Position _examined;
private Mock<ITimeoutControl> _timeoutControl; private Mock<ITimeoutControl> _timeoutControl;
public Http1ConnectionTests() public Http1ConnectionTests()

View File

@ -2,8 +2,8 @@
// 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.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.IO.Pipelines.Testing;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
string expectedVersion) string expectedVersion)
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine) public void ParseRequestLineReturnsFalseWhenGivenIncompleteRequestLines(string requestLine)
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine) public void ParseRequestLineDoesNotConsumeIncompleteRequestLine(string requestLine)
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.False(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
.Returns(true); .Returns(true);
var parser = CreateParser(mockTrace.Object); var parser = CreateParser(mockTrace.Object);
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
var exception = Assert.Throws<BadHttpRequestException>(() => var exception = Assert.Throws<BadHttpRequestException>(() =>
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
.Returns(true); .Returns(true);
var parser = CreateParser(mockTrace.Object); var parser = CreateParser(mockTrace.Object);
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
var exception = Assert.Throws<BadHttpRequestException>(() => var exception = Assert.Throws<BadHttpRequestException>(() =>
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
.Returns(true); .Returns(true);
var parser = CreateParser(mockTrace.Object); var parser = CreateParser(mockTrace.Object);
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(requestLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
var exception = Assert.Throws<BadHttpRequestException>(() => var exception = Assert.Throws<BadHttpRequestException>(() =>
@ -179,7 +179,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
Assert.False(parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes)); Assert.False(parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
} }
@ -204,7 +204,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes); parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
const string headerLine = "Header: value\r\n\r"; const string headerLine = "Header: value\r\n\r";
var buffer1 = ReadableBuffer.Create(Encoding.ASCII.GetBytes(headerLine)); var buffer1 = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(headerLine));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
Assert.False(parser.ParseHeaders(requestHandler, buffer1, out var consumed, out var examined, out var consumedBytes)); Assert.False(parser.ParseHeaders(requestHandler, buffer1, out var consumed, out var examined, out var consumedBytes));
@ -302,7 +302,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(buffer1.End, examined); Assert.Equal(buffer1.End, examined);
Assert.Equal(headerLine.Length - 1, consumedBytes); Assert.Equal(headerLine.Length - 1, consumedBytes);
var buffer2 = ReadableBuffer.Create(Encoding.ASCII.GetBytes("\r\n")); var buffer2 = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("\r\n"));
Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes)); Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes));
Assert.Equal(buffer2.End, consumed); Assert.Equal(buffer2.End, consumed);
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
.Returns(true); .Returns(true);
var parser = CreateParser(mockTrace.Object); var parser = CreateParser(mockTrace.Object);
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
var exception = Assert.Throws<BadHttpRequestException>(() => var exception = Assert.Throws<BadHttpRequestException>(() =>
@ -341,7 +341,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var parser = CreateParser(mockTrace.Object); var parser = CreateParser(mockTrace.Object);
// Invalid request line // Invalid request line
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n")); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n"));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
var exception = Assert.Throws<BadHttpRequestException>(() => var exception = Assert.Throws<BadHttpRequestException>(() =>
@ -351,7 +351,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode); Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode);
// Unrecognized HTTP version // Unrecognized HTTP version
buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n")); buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n"));
exception = Assert.Throws<BadHttpRequestException>(() => exception = Assert.Throws<BadHttpRequestException>(() =>
parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined));
@ -360,7 +360,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode); Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode);
// Invalid request header // Invalid request header
buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("Header: value\n\r\n")); buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes("Header: value\n\r\n"));
exception = Assert.Throws<BadHttpRequestException>(() => exception = Assert.Throws<BadHttpRequestException>(() =>
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes)); parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes));
@ -369,27 +369,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
} }
[Fact]
public void ParseRequestLineSplitBufferWithoutNewLineDoesNotUpdateConsumed()
{
var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = BufferUtilities.CreateBuffer("GET ", "/");
var requestHandler = new RequestHandler();
var result = parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined);
Assert.False(result);
Assert.Equal(buffer.Start, consumed);
Assert.Equal(buffer.End, examined);
}
private void VerifyHeader( private void VerifyHeader(
string headerName, string headerName,
string rawHeaderValue, string rawHeaderValue,
string expectedHeaderValue) string expectedHeaderValue)
{ {
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n")); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes($"{headerName}:{rawHeaderValue}\r\n"));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes); parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);
@ -407,7 +393,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.True(expectedHeaderNames.Count() == expectedHeaderValues.Count(), $"{nameof(expectedHeaderNames)} and {nameof(expectedHeaderValues)} sizes must match"); Assert.True(expectedHeaderNames.Count() == expectedHeaderValues.Count(), $"{nameof(expectedHeaderNames)} and {nameof(expectedHeaderValues)} sizes must match");
var parser = CreateParser(Mock.Of<IKestrelTrace>()); var parser = CreateParser(Mock.Of<IKestrelTrace>());
var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(rawHeaders)); var buffer = new ReadOnlyBuffer(Encoding.ASCII.GetBytes(rawHeaders));
var requestHandler = new RequestHandler(); var requestHandler = new RequestHandler();
parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes); parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes);

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
( (
pool: _memoryPool, pool: _memoryPool,
readerScheduler: Mock.Of<IScheduler>() readerScheduler: Mock.Of<Scheduler>()
); );
using (var socketOutput = CreateOutputProducer(pipeOptions)) using (var socketOutput = CreateOutputProducer(pipeOptions))

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize; serviceContext.ServerOptions.Limits.MaxResponseBufferSize = maxResponseBufferSize;
serviceContext.ThreadPool = new LoggingThreadPool(null); serviceContext.ThreadPool = new LoggingThreadPool(null);
var mockScheduler = Mock.Of<IScheduler>(); var mockScheduler = Mock.Of<Scheduler>();
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler); var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow); Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow);
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize; serviceContext.ServerOptions.Limits.MaxRequestBufferSize = maxRequestBufferSize;
serviceContext.ThreadPool = new LoggingThreadPool(null); serviceContext.ThreadPool = new LoggingThreadPool(null);
var mockScheduler = Mock.Of<IScheduler>(); var mockScheduler = Mock.Of<Scheduler>();
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler); var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow); Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow);
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeLow); Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeLow);
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeHigh); Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedInputPipeOptions.MaximumSizeHigh);
Assert.Same(serviceContext.ThreadPool, connectionLifetime.AdaptedInputPipeOptions.ReaderScheduler); Assert.Same(serviceContext.ThreadPool, connectionLifetime.AdaptedInputPipeOptions.ReaderScheduler);
Assert.Same(InlineScheduler.Default, connectionLifetime.AdaptedInputPipeOptions.WriterScheduler); Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedInputPipeOptions.WriterScheduler);
} }
[Theory] [Theory]
@ -87,8 +87,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeLow); Assert.Equal(expectedMaximumSizeLow, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeLow);
Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeHigh); Assert.Equal(expectedMaximumSizeHigh, connectionLifetime.AdaptedOutputPipeOptions.MaximumSizeHigh);
Assert.Same(InlineScheduler.Default, connectionLifetime.AdaptedOutputPipeOptions.ReaderScheduler); Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.ReaderScheduler);
Assert.Same(InlineScheduler.Default, connectionLifetime.AdaptedOutputPipeOptions.WriterScheduler); Assert.Same(Scheduler.Inline, connectionLifetime.AdaptedOutputPipeOptions.WriterScheduler);
} }
} }
} }

View File

@ -117,11 +117,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler }; var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
var transport = new LibuvTransport(mockLibuv, transportContext, null); var transport = new LibuvTransport(mockLibuv, transportContext, null);
var thread = new LibuvThread(transport); var thread = new LibuvThread(transport);
var mockScheduler = new Mock<IScheduler>(); var mockScheduler = new Mock<Scheduler>();
Action backPressure = null; Action backPressure = null;
mockScheduler.Setup(m => m.Schedule(It.IsAny<Action<object>>(), It.IsAny<object>())).Callback<Action<object>, object>((a, o) => mockScheduler.Setup(m => m.Schedule(It.IsAny<Action>())).Callback<Action>(a =>
{ {
backPressure = () => a(o); backPressure = a;
}); });
mockConnectionHandler.InputOptions = pool => mockConnectionHandler.InputOptions = pool =>
new PipeOptions( new PipeOptions(

View File

@ -2,6 +2,7 @@
// 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.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@ -68,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
await writeRequest.WriteAsync( await writeRequest.WriteAsync(
serverConnectionPipe, serverConnectionPipe,
ReadableBuffer.Create(new byte[] { 1, 2, 3, 4 })); new ReadOnlyBuffer(new byte[] { 1, 2, 3, 4 }));
writeRequest.Dispose(); writeRequest.Dispose();
serverConnectionPipe.Dispose(); serverConnectionPipe.Dispose();

View File

@ -2,6 +2,7 @@
// 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.Buffers;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -161,7 +162,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
{ {
var req = new UvWriteReq(_logger); var req = new UvWriteReq(_logger);
req.DangerousInit(loop); req.DangerousInit(loop);
var block = ReadableBuffer.Create(new byte[] { 65, 66, 67, 68, 69 }); var block = new ReadOnlyBuffer(new byte[] { 65, 66, 67, 68, 69 });
await req.WriteAsync( await req.WriteAsync(
tcp2, tcp2,