Migrate to new pipe APIs (#2124)

This commit is contained in:
Pavel Krymets 2017-11-13 15:04:54 -08:00 committed by GitHub
parent 53b4697269
commit 73a37363e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 352 additions and 274 deletions

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -22,8 +23,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
[IterationSetup] [IterationSetup]
public void Setup() public void Setup()
{ {
var pipeFactory = new PipeFactory(); var bufferPool = new MemoryPool();
var pair = pipeFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(bufferPool);
var serviceContext = new ServiceContext var serviceContext = new ServiceContext
{ {
@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
ServiceContext = serviceContext, ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = pipeFactory, BufferPool = bufferPool,
TimeoutControl = new MockTimeoutControl(), TimeoutControl = new MockTimeoutControl(),
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport Transport = pair.Transport

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.Text; using System.Text;
using System.Threading; using System.Threading;
@ -93,31 +94,34 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
private TestHttp1Connection<object> MakeHttp1Connection() private TestHttp1Connection<object> MakeHttp1Connection()
{ {
var pipeFactory = new PipeFactory(); using (var memoryPool = new MemoryPool())
var pair = pipeFactory.CreateConnectionPair();
_pair = pair;
var serviceContext = new ServiceContext
{ {
DateHeaderValueManager = new DateHeaderValueManager(), var pair = PipeFactory.CreateConnectionPair(memoryPool);
ServerOptions = new KestrelServerOptions(), _pair = pair;
Log = new MockTrace(),
HttpParserFactory = f => new HttpParser<Http1ParsingHandler>()
};
var http1Connection = new TestHttp1Connection<object>(application: null, context: new Http1ConnectionContext var serviceContext = new ServiceContext
{ {
ServiceContext = serviceContext, DateHeaderValueManager = new DateHeaderValueManager(),
ConnectionFeatures = new FeatureCollection(), ServerOptions = new KestrelServerOptions(),
PipeFactory = pipeFactory, Log = new MockTrace(),
Application = pair.Application, HttpParserFactory = f => new HttpParser<Http1ParsingHandler>()
Transport = pair.Transport };
});
http1Connection.Reset(); var http1Connection = new TestHttp1Connection<object>(
http1Connection.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive); application: null, context: new Http1ConnectionContext
{
ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(),
BufferPool = memoryPool,
Application = pair.Application,
Transport = pair.Transport
});
return http1Connection; http1Connection.Reset();
http1Connection.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
return http1Connection;
}
} }
[IterationCleanup] [IterationCleanup]

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.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -77,8 +78,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public HttpProtocolFeatureCollection() public HttpProtocolFeatureCollection()
{ {
var pipeFactory = new PipeFactory(); var bufferPool = new MemoryPool();
var pair = pipeFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(bufferPool);
var serviceContext = new ServiceContext var serviceContext = new ServiceContext
{ {
@ -92,7 +93,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
ServiceContext = serviceContext, ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = pipeFactory, BufferPool = bufferPool,
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport Transport = pair.Transport
}); });

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using System.Threading.Tasks; using System.Threading.Tasks;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
@ -14,13 +15,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
private const int InnerLoopCount = 512; private const int InnerLoopCount = 512;
private IPipe _pipe; private IPipe _pipe;
private PipeFactory _pipelineFactory; private BufferPool _bufferPool;
[IterationSetup] [IterationSetup]
public void Setup() public void Setup()
{ {
_pipelineFactory = new PipeFactory(); _bufferPool = new MemoryPool();
_pipe = _pipelineFactory.Create(); _pipe = new Pipe(new PipeOptions(_bufferPool));
} }
[Benchmark(OperationsPerInvoke = InnerLoopCount)] [Benchmark(OperationsPerInvoke = InnerLoopCount)]

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -18,13 +19,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public Http1Connection<object> Http1Connection { get; set; } public Http1Connection<object> Http1Connection { get; set; }
public PipeFactory PipeFactory { get; set; }
[IterationSetup] [IterationSetup]
public void Setup() public void Setup()
{ {
var pipeFactory = new PipeFactory(); var bufferPool = new MemoryPool();
var pair = pipeFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(bufferPool);
var serviceContext = new ServiceContext var serviceContext = new ServiceContext
{ {
@ -38,7 +37,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
ServiceContext = serviceContext, ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = pipeFactory, BufferPool = bufferPool,
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport, Transport = pair.Transport,
TimeoutControl = new MockTimeoutControl() TimeoutControl = new MockTimeoutControl()
@ -47,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
http1Connection.Reset(); http1Connection.Reset();
Http1Connection = http1Connection; Http1Connection = http1Connection;
Pipe = pipeFactory.Create(); Pipe = new Pipe(new PipeOptions(bufferPool));
} }
[Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)] [Benchmark(Baseline = true, OperationsPerInvoke = RequestParsingData.InnerLoopCount)]

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
@ -170,8 +171,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
[IterationSetup] [IterationSetup]
public void Setup() public void Setup()
{ {
var pipeFactory = new PipeFactory(); var bufferPool = new MemoryPool();
var pair = pipeFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(bufferPool);
var serviceContext = new ServiceContext var serviceContext = new ServiceContext
{ {
@ -185,7 +186,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
ServiceContext = serviceContext, ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = pipeFactory, BufferPool = bufferPool,
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport Transport = pair.Transport
}); });

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.Text; using System.Text;
using System.Threading; using System.Threading;
@ -110,8 +111,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
[IterationSetup] [IterationSetup]
public void Setup() public void Setup()
{ {
var pipeFactory = new PipeFactory(); var bufferPool = new MemoryPool();
var pair = pipeFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(bufferPool);
var serviceContext = new ServiceContext var serviceContext = new ServiceContext
{ {
@ -121,15 +122,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
HttpParserFactory = f => new HttpParser<Http1ParsingHandler>() HttpParserFactory = f => new HttpParser<Http1ParsingHandler>()
}; };
var http1Connection = new TestHttp1Connection<object>(application: null, context: new Http1ConnectionContext var http1Connection = new TestHttp1Connection<object>(
{ application: null, context: new Http1ConnectionContext
ServiceContext = serviceContext, {
ConnectionFeatures = new FeatureCollection(), ServiceContext = serviceContext,
PipeFactory = pipeFactory, ConnectionFeatures = new FeatureCollection(),
TimeoutControl = new MockTimeoutControl(), BufferPool = bufferPool,
Application = pair.Application, TimeoutControl = new MockTimeoutControl(),
Transport = pair.Transport Application = pair.Application,
}); Transport = pair.Transport
});
http1Connection.Reset(); http1Connection.Reset();

View File

@ -28,12 +28,13 @@
<MoqPackageVersion>4.7.49</MoqPackageVersion> <MoqPackageVersion>4.7.49</MoqPackageVersion>
<NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion> <NewtonsoftJsonPackageVersion>10.0.1</NewtonsoftJsonPackageVersion>
<SystemBuffersPackageVersion>4.4.0</SystemBuffersPackageVersion> <SystemBuffersPackageVersion>4.4.0</SystemBuffersPackageVersion>
<SystemIOPipelinesPackageVersion>0.1.0-e170811-6</SystemIOPipelinesPackageVersion> <SystemIOPipelinesPackageVersion>0.1.0-alpha-002</SystemIOPipelinesPackageVersion>
<SystemMemoryPackageVersion>4.4.0-preview3-25519-03</SystemMemoryPackageVersion> <SystemIOPipelinesTestingPackageVersion>0.1.0-alpha-002</SystemIOPipelinesTestingPackageVersion>
<SystemNumericsVectorsPackageVersion>4.4.0</SystemNumericsVectorsPackageVersion> <SystemMemoryPackageVersion>4.5.0-preview1-25902-08</SystemMemoryPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.4.0</SystemRuntimeCompilerServicesUnsafePackageVersion> <SystemNumericsVectorsPackageVersion>4.5.0-preview1-25902-08</SystemNumericsVectorsPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview1-25902-08</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>4.4.0</SystemSecurityCryptographyCngPackageVersion> <SystemSecurityCryptographyCngPackageVersion>4.4.0</SystemSecurityCryptographyCngPackageVersion>
<SystemTextEncodingsWebUtf8PackageVersion>0.1.0-e170811-6</SystemTextEncodingsWebUtf8PackageVersion> <SystemTextEncodingsWebUtf8PackageVersion>0.1.0-alpha-002</SystemTextEncodingsWebUtf8PackageVersion>
<SystemThreadingTasksExtensionsPackageVersion>4.4.0</SystemThreadingTasksExtensionsPackageVersion> <SystemThreadingTasksExtensionsPackageVersion>4.4.0</SystemThreadingTasksExtensionsPackageVersion>
<XunitAnalyzersPackageVersion>0.7.0</XunitAnalyzersPackageVersion> <XunitAnalyzersPackageVersion>0.7.0</XunitAnalyzersPackageVersion>
<XunitPackageVersion>2.3.0</XunitPackageVersion> <XunitPackageVersion>2.3.0</XunitPackageVersion>

View File

@ -1,2 +1,2 @@
version:2.1.0-preview1-15549 version:2.1.0-preview1-15551
commithash:f570e08585fec510dd60cd4bfe8795388b757a95 commithash:8fad9553b48533fddbb16a423ea55b9710ea2e63

View File

@ -2,7 +2,9 @@
// 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.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Protocols;
@ -34,10 +36,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
// REVIEW: Unfortunately, we still need to use the service context to create the pipes since the settings // REVIEW: Unfortunately, we still need to use the service context to create the pipes since the settings
// for the scheduler and limits are specified here // for the scheduler and limits are specified here
var inputOptions = GetInputPipeOptions(_serviceContext, transportFeature.InputWriterScheduler); var inputOptions = GetInputPipeOptions(_serviceContext, connectionContext.BufferPool, transportFeature.InputWriterScheduler);
var outputOptions = GetOutputPipeOptions(_serviceContext, transportFeature.OutputReaderScheduler); var outputOptions = GetOutputPipeOptions(_serviceContext, connectionContext.BufferPool, transportFeature.OutputReaderScheduler);
var pair = connectionContext.PipeFactory.CreateConnectionPair(inputOptions, outputOptions); var pair = PipeFactory.CreateConnectionPair(inputOptions, outputOptions);
// Set the transport and connection id // Set the transport and connection id
connectionContext.ConnectionId = CorrelationIdGenerator.GetNextId(); connectionContext.ConnectionId = CorrelationIdGenerator.GetNextId();
@ -81,21 +83,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
} }
// Internal for testing // Internal for testing
internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, IScheduler writerScheduler) => new PipeOptions internal static PipeOptions GetInputPipeOptions(ServiceContext serviceContext, BufferPool bufferPool, IScheduler writerScheduler) => new PipeOptions
{ (
ReaderScheduler = serviceContext.ThreadPool, bufferPool: bufferPool,
WriterScheduler = writerScheduler, readerScheduler: serviceContext.ThreadPool,
MaximumSizeHigh = serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0, writerScheduler: writerScheduler,
MaximumSizeLow = serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0 maximumSizeHigh: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
}; maximumSizeLow: serviceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
);
internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, IScheduler readerScheduler) => new PipeOptions internal static PipeOptions GetOutputPipeOptions(ServiceContext serviceContext, BufferPool bufferPool, IScheduler readerScheduler) => new PipeOptions
{ (
ReaderScheduler = readerScheduler, bufferPool: bufferPool,
WriterScheduler = serviceContext.ThreadPool, readerScheduler: readerScheduler,
MaximumSizeHigh = GetOutputResponseBufferSize(serviceContext), writerScheduler: serviceContext.ThreadPool,
MaximumSizeLow = GetOutputResponseBufferSize(serviceContext) maximumSizeHigh: GetOutputResponseBufferSize(serviceContext),
}; maximumSizeLow: GetOutputResponseBufferSize(serviceContext)
);
private static long GetOutputResponseBufferSize(ServiceContext serviceContext) private static long GetOutputResponseBufferSize(ServiceContext serviceContext)
{ {

View File

@ -209,7 +209,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (pathEncoded) if (pathEncoded)
{ {
// URI was encoded, unescape and then parse as UTF-8 // URI was encoded, unescape and then parse as UTF-8
// Disabling warning temporary
#pragma warning disable 618
var pathLength = UrlEncoder.Decode(path, path); var pathLength = UrlEncoder.Decode(path, path);
#pragma warning restore 618
// Removing dot segments must be done after unescaping. From RFC 3986: // Removing dot segments must be done after unescaping. From RFC 3986:
// //

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public string ConnectionId { get; set; } public string ConnectionId { get; set; }
public ServiceContext ServiceContext { get; set; } public ServiceContext ServiceContext { get; set; }
public IFeatureCollection ConnectionFeatures { get; set; } public IFeatureCollection ConnectionFeatures { get; set; }
public PipeFactory PipeFactory { get; set; } public BufferPool BufferPool { get; set; }
public IPEndPoint RemoteEndPoint { get; set; } public IPEndPoint RemoteEndPoint { get; set; }
public IPEndPoint LocalEndPoint { get; set; } public IPEndPoint LocalEndPoint { get; set; }
public ITimeoutControl TimeoutControl { get; set; } public ITimeoutControl TimeoutControl { get; set; }

View File

@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var writableBuffer = default(WritableBuffer); var writableBuffer = default(WritableBuffer);
long bytesWritten = 0;
lock (_contextLock) lock (_contextLock)
{ {
if (_completed) if (_completed)
@ -181,17 +181,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (buffer.Count > 0) if (buffer.Count > 0)
{ {
writer.Write(buffer.Array, buffer.Offset, buffer.Count); writer.Write(buffer.Array, buffer.Offset, buffer.Count);
bytesWritten += buffer.Count;
} }
writableBuffer.Commit(); writableBuffer.Commit();
} }
return FlushAsync(writableBuffer, cancellationToken); return FlushAsync(writableBuffer, bytesWritten, cancellationToken);
} }
// Single caller, at end of method - so inline // Single caller, at end of method - so inline
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private Task FlushAsync(WritableBuffer writableBuffer, CancellationToken cancellationToken) private Task FlushAsync(WritableBuffer writableBuffer, long bytesWritten, CancellationToken cancellationToken)
{ {
var awaitable = writableBuffer.FlushAsync(cancellationToken); var awaitable = writableBuffer.FlushAsync(cancellationToken);
if (awaitable.IsCompleted) if (awaitable.IsCompleted)
@ -199,7 +200,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
// The flush task can't fail today // The flush task can't fail today
return Task.CompletedTask; return Task.CompletedTask;
} }
return FlushAsyncAwaited(awaitable, writableBuffer.BytesWritten, cancellationToken); return FlushAsyncAwaited(awaitable, bytesWritten, cancellationToken);
} }
private async Task FlushAsyncAwaited(WritableBufferAwaitable awaitable, long count, CancellationToken cancellationToken) private async Task FlushAsyncAwaited(WritableBufferAwaitable awaitable, long count, CancellationToken cancellationToken)

View File

@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public IHttpResponseControl HttpResponseControl { get; set; } public IHttpResponseControl HttpResponseControl { get; set; }
public IPipe RequestBodyPipe { get; } public Pipe RequestBodyPipe { get; }
public ServiceContext ServiceContext => _context.ServiceContext; public ServiceContext ServiceContext => _context.ServiceContext;
private IPEndPoint LocalEndPoint => _context.LocalEndPoint; private IPEndPoint LocalEndPoint => _context.LocalEndPoint;
@ -1301,13 +1301,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
Log.ApplicationError(ConnectionId, TraceIdentifier, ex); Log.ApplicationError(ConnectionId, TraceIdentifier, ex);
} }
private IPipe CreateRequestBodyPipe() private Pipe CreateRequestBodyPipe()
=> _context.PipeFactory.Create(new PipeOptions => new Pipe(new PipeOptions
{ (
ReaderScheduler = ServiceContext.ThreadPool, bufferPool: _context.BufferPool,
WriterScheduler = InlineScheduler.Default, readerScheduler: ServiceContext.ThreadPool,
MaximumSizeHigh = 1, writerScheduler: InlineScheduler.Default,
MaximumSizeLow = 1 maximumSizeHigh: 1,
}); maximumSizeLow: 1
));
} }
} }

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
string ConnectionId { get; set; } string ConnectionId { get; set; }
ServiceContext ServiceContext { get; set; } ServiceContext ServiceContext { get; set; }
IFeatureCollection ConnectionFeatures { get; set; } IFeatureCollection ConnectionFeatures { get; set; }
PipeFactory PipeFactory { get; set; } BufferPool BufferPool { get; set; }
IPEndPoint RemoteEndPoint { get; set; } IPEndPoint RemoteEndPoint { get; set; }
IPEndPoint LocalEndPoint { get; set; } IPEndPoint LocalEndPoint { get; set; }
} }

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return buffer.ToArray(); return buffer.ToArray();
} }
public static ArraySegment<byte> GetArray(this Buffer<byte> buffer) public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
{ {
ArraySegment<byte> result; ArraySegment<byte> result;
if (!buffer.TryGetArray(out result)) if (!buffer.TryGetArray(out result))
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return result; return result;
} }
public unsafe static void WriteAsciiNoValidation(ref WritableBufferWriter buffer, string data) public unsafe static void WriteAsciiNoValidation(ref this WritableBufferWriter buffer, string data)
{ {
if (string.IsNullOrEmpty(data)) if (string.IsNullOrEmpty(data))
{ {
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void WriteNumeric(ref WritableBufferWriter buffer, ulong number) public unsafe static void WriteNumeric(ref this WritableBufferWriter buffer, ulong number)
{ {
const byte AsciiDigitStart = (byte)'0'; const byte AsciiDigitStart = (byte)'0';
@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private static void WriteNumericMultiWrite(ref WritableBufferWriter buffer, ulong number) private static void WriteNumericMultiWrite(ref this WritableBufferWriter buffer, ulong number)
{ {
const byte AsciiDigitStart = (byte)'0'; const byte AsciiDigitStart = (byte)'0';
@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private unsafe static void WriteAsciiMultiWrite(ref WritableBufferWriter buffer, string data) private unsafe static void WriteAsciiMultiWrite(ref this WritableBufferWriter buffer, string data)
{ {
var remaining = data.Length; var remaining = data.Length;

View File

@ -397,7 +397,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
StreamId = _incomingFrame.StreamId, StreamId = _incomingFrame.StreamId,
ServiceContext = _context.ServiceContext, ServiceContext = _context.ServiceContext,
ConnectionFeatures = _context.ConnectionFeatures, ConnectionFeatures = _context.ConnectionFeatures,
PipeFactory = _context.PipeFactory, BufferPool = _context.BufferPool,
LocalEndPoint = _context.LocalEndPoint, LocalEndPoint = _context.LocalEndPoint,
RemoteEndPoint = _context.RemoteEndPoint, RemoteEndPoint = _context.RemoteEndPoint,
StreamLifetimeHandler = this, StreamLifetimeHandler = this,

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
public string ConnectionId { get; set; } public string ConnectionId { get; set; }
public ServiceContext ServiceContext { get; set; } public ServiceContext ServiceContext { get; set; }
public IFeatureCollection ConnectionFeatures { get; set; } public IFeatureCollection ConnectionFeatures { get; set; }
public PipeFactory PipeFactory { get; set; } public BufferPool BufferPool { get; set; }
public IPEndPoint LocalEndPoint { get; set; } public IPEndPoint LocalEndPoint { get; set; }
public IPEndPoint RemoteEndPoint { get; set; } public IPEndPoint RemoteEndPoint { get; set; }

View File

@ -1,6 +1,7 @@
// 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.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
public int StreamId { get; set; } public int StreamId { get; set; }
public ServiceContext ServiceContext { get; set; } public ServiceContext ServiceContext { get; set; }
public IFeatureCollection ConnectionFeatures { get; set; } public IFeatureCollection ConnectionFeatures { get; set; }
public PipeFactory PipeFactory { get; set; } public BufferPool BufferPool { get; set; }
public IPEndPoint RemoteEndPoint { get; set; } public IPEndPoint RemoteEndPoint { get; set; }
public IPEndPoint LocalEndPoint { get; set; } public IPEndPoint LocalEndPoint { get; set; }
public IHttp2StreamLifetimeHandler StreamLifetimeHandler { get; set; } public IHttp2StreamLifetimeHandler StreamLifetimeHandler { get; set; }

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.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -65,24 +66,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
public IPEndPoint LocalEndPoint => _context.LocalEndPoint; public IPEndPoint LocalEndPoint => _context.LocalEndPoint;
public IPEndPoint RemoteEndPoint => _context.RemoteEndPoint; public IPEndPoint RemoteEndPoint => _context.RemoteEndPoint;
private PipeFactory PipeFactory => _context.PipeFactory; private BufferPool BufferPool => _context.BufferPool;
// Internal for testing // Internal for testing
internal PipeOptions AdaptedInputPipeOptions => new PipeOptions internal PipeOptions AdaptedInputPipeOptions => new PipeOptions
{ (
ReaderScheduler = _context.ServiceContext.ThreadPool, bufferPool: BufferPool,
WriterScheduler = InlineScheduler.Default, readerScheduler: _context.ServiceContext.ThreadPool,
MaximumSizeHigh = _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0, writerScheduler: InlineScheduler.Default,
MaximumSizeLow = _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0 maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0,
}; maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxRequestBufferSize ?? 0
);
internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions internal PipeOptions AdaptedOutputPipeOptions => new PipeOptions
{ (
ReaderScheduler = InlineScheduler.Default, bufferPool: BufferPool,
WriterScheduler = InlineScheduler.Default, readerScheduler: InlineScheduler.Default,
MaximumSizeHigh = _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0, writerScheduler: InlineScheduler.Default,
MaximumSizeLow = _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0 maximumSizeHigh: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0,
}; maximumSizeLow: _context.ServiceContext.ServerOptions.Limits.MaxResponseBufferSize ?? 0
);
private IKestrelTrace Log => _context.ServiceContext.Log; private IKestrelTrace Log => _context.ServiceContext.Log;
@ -107,8 +110,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
{ {
adaptedPipeline = new AdaptedPipeline(transport, adaptedPipeline = new AdaptedPipeline(transport,
application, application,
PipeFactory.Create(AdaptedInputPipeOptions), new Pipe(AdaptedInputPipeOptions),
PipeFactory.Create(AdaptedOutputPipeOptions)); new Pipe(AdaptedOutputPipeOptions));
transport = adaptedPipeline; transport = adaptedPipeline;
} }
@ -180,7 +183,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
{ {
ConnectionId = _context.ConnectionId, ConnectionId = _context.ConnectionId,
ConnectionFeatures = _context.ConnectionFeatures, ConnectionFeatures = _context.ConnectionFeatures,
PipeFactory = PipeFactory, BufferPool = BufferPool,
LocalEndPoint = LocalEndPoint, LocalEndPoint = LocalEndPoint,
RemoteEndPoint = RemoteEndPoint, RemoteEndPoint = RemoteEndPoint,
ServiceContext = _context.ServiceContext, ServiceContext = _context.ServiceContext,
@ -197,7 +200,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
ConnectionId = _context.ConnectionId, ConnectionId = _context.ConnectionId,
ServiceContext = _context.ServiceContext, ServiceContext = _context.ServiceContext,
ConnectionFeatures = _context.ConnectionFeatures, ConnectionFeatures = _context.ConnectionFeatures,
PipeFactory = PipeFactory, BufferPool = BufferPool,
LocalEndPoint = LocalEndPoint, LocalEndPoint = LocalEndPoint,
RemoteEndPoint = RemoteEndPoint, RemoteEndPoint = RemoteEndPoint,
Application = application, Application = application,

View File

@ -1,6 +1,7 @@
// 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.Generic; using System.Collections.Generic;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
public ServiceContext ServiceContext { get; set; } public ServiceContext ServiceContext { get; set; }
public IFeatureCollection ConnectionFeatures { get; set; } public IFeatureCollection ConnectionFeatures { get; set; }
public IList<IConnectionAdapter> ConnectionAdapters { get; set; } public IList<IConnectionAdapter> ConnectionAdapters { get; set; }
public PipeFactory PipeFactory { get; set; } public BufferPool BufferPool { get; set; }
public IPEndPoint LocalEndPoint { get; set; } public IPEndPoint LocalEndPoint { get; set; }
public IPEndPoint RemoteEndPoint { get; set; } public IPEndPoint RemoteEndPoint { get; set; }
public IPipeConnection Transport { get; set; } public IPipeConnection Transport { get; set; }

View File

@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
Protocols = _protocols, Protocols = _protocols,
ServiceContext = _serviceContext, ServiceContext = _serviceContext,
ConnectionFeatures = connectionContext.Features, ConnectionFeatures = connectionContext.Features,
PipeFactory = connectionContext.PipeFactory, BufferPool = connectionContext.BufferPool,
ConnectionAdapters = _connectionAdapters, ConnectionAdapters = _connectionAdapters,
Transport = connectionContext.Transport, Transport = connectionContext.Transport,
Application = transportFeature.Application Application = transportFeature.Application

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Buffers;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO.Pipelines; using System.IO.Pipelines;
@ -95,7 +96,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
set => LocalPort = value; set => LocalPort = value;
} }
PipeFactory IConnectionTransportFeature.PipeFactory => PipeFactory; BufferPool IConnectionTransportFeature.BufferPool => BufferPool;
IPipeConnection IConnectionTransportFeature.Transport IPipeConnection IConnectionTransportFeature.Transport
{ {

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using System.Threading;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
{ {
@ -20,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal
public string ConnectionId { get; set; } public string ConnectionId { get; set; }
public virtual PipeFactory PipeFactory { get; } public virtual BufferPool BufferPool { get; }
public virtual IScheduler InputWriterScheduler { get; } public virtual IScheduler InputWriterScheduler { get; }
public virtual IScheduler OutputReaderScheduler { get; } public virtual IScheduler OutputReaderScheduler { get; }

View File

@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
private readonly UvStreamHandle _socket; private readonly UvStreamHandle _socket;
private WritableBuffer? _currentWritableBuffer; private WritableBuffer? _currentWritableBuffer;
private BufferHandle _bufferHandle; private MemoryHandle _bufferHandle;
public LibuvConnection(ListenerContext context, UvStreamHandle socket) : base(context) public LibuvConnection(ListenerContext context, UvStreamHandle socket) : base(context)
{ {
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
_bufferHandle = currentWritableBuffer.Buffer.Retain(true); _bufferHandle = currentWritableBuffer.Buffer.Retain(true);
return handle.Libuv.buf_init((IntPtr)_bufferHandle.PinnedPointer, currentWritableBuffer.Buffer.Length); return handle.Libuv.buf_init((IntPtr)_bufferHandle.Pointer, currentWritableBuffer.Buffer.Length);
} }
private static void ReadCallback(UvStreamHandle handle, int status, object state) private static void ReadCallback(UvStreamHandle handle, int status, object state)

View File

@ -1,8 +1,10 @@
// 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.Net; using System.Net;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
@ -15,8 +17,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
} }
public ListenerContext ListenerContext { get; set; } public ListenerContext ListenerContext { get; set; }
public override PipeFactory PipeFactory => ListenerContext.Thread.PipeFactory; public override BufferPool BufferPool => ListenerContext.Thread.BufferPool;
public override IScheduler InputWriterScheduler => ListenerContext.Thread; public override IScheduler InputWriterScheduler => ListenerContext.Thread;
public override IScheduler OutputReaderScheduler => ListenerContext.Thread; public override IScheduler OutputReaderScheduler => ListenerContext.Thread;
} }

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.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO.Pipelines; using System.IO.Pipelines;
@ -55,7 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
#endif #endif
QueueCloseHandle = PostCloseHandle; QueueCloseHandle = PostCloseHandle;
QueueCloseAsyncHandle = EnqueueCloseHandle; QueueCloseAsyncHandle = EnqueueCloseHandle;
PipeFactory = new PipeFactory(); BufferPool = new MemoryPool();
WriteReqPool = new WriteReqPool(this, _log); WriteReqPool = new WriteReqPool(this, _log);
} }
@ -68,7 +69,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
public UvLoopHandle Loop { get { return _loop; } } public UvLoopHandle Loop { get { return _loop; } }
public PipeFactory PipeFactory { get; } public BufferPool BufferPool { get; }
public WriteReqPool WriteReqPool { get; } public WriteReqPool WriteReqPool { get; }
@ -295,7 +296,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
} }
finally finally
{ {
PipeFactory.Dispose(); BufferPool.Dispose();
WriteReqPool.Dispose(); WriteReqPool.Dispose();
_threadTcs.SetResult(null); _threadTcs.SetResult(null);

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
private LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>(); private LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>();
private List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1); private List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1);
private List<BufferHandle> _handles = new List<BufferHandle>(BUFFER_COUNT + 1); private List<MemoryHandle> _handles = new List<MemoryHandle>(BUFFER_COUNT + 1);
public UvWriteReq(ILibuvTrace logger) : base(logger) public UvWriteReq(ILibuvTrace logger) : base(logger)
{ {
@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
// Fast path for single buffer // Fast path for single buffer
pBuffers[0] = Libuv.buf_init( pBuffers[0] = Libuv.buf_init(
(IntPtr)memoryHandle.PinnedPointer, (IntPtr)memoryHandle.Pointer,
memory.Length); memory.Length);
} }
else else
@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
// create and pin each segment being written // create and pin each segment being written
pBuffers[index] = Libuv.buf_init( pBuffers[index] = Libuv.buf_init(
(IntPtr)memoryHandle.PinnedPointer, (IntPtr)memoryHandle.Pointer,
memory.Length); memory.Length);
index++; index++;
} }
@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
} }
// Safe handle has instance method called Unpin // Safe handle has instance method called Unpin
// so using UnpinGcHandles to avoid conflict // so using UnpinGcHandles to avoid conflict
private void UnpinGcHandles() private void UnpinGcHandles()
{ {
var pinList = _pins; var pinList = _pins;
@ -254,4 +254,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networkin
} }
} }
} }
} }

View File

@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
{ {
public static class BufferExtensions public static class BufferExtensions
{ {
public static ArraySegment<byte> GetArray(this Buffer<byte> buffer) public static ArraySegment<byte> GetArray(this Memory<byte> buffer)
{ {
ArraySegment<byte> result; ArraySegment<byte> result;
if (!buffer.TryGetArray(out result)) if (!buffer.TryGetArray(out result))
@ -17,4 +17,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
return result; return result;
} }
} }
} }

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.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Pipelines; using System.IO.Pipelines;
@ -9,6 +11,7 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Protocols; using Microsoft.AspNetCore.Protocols;
using System.Threading;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal; using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -25,14 +28,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
private volatile bool _aborted; private volatile bool _aborted;
internal SocketConnection(Socket socket, PipeFactory pipeFactory, ISocketsTrace trace) internal SocketConnection(Socket socket, BufferPool bufferPool, ISocketsTrace trace)
{ {
Debug.Assert(socket != null); Debug.Assert(socket != null);
Debug.Assert(pipeFactory != null); Debug.Assert(bufferPool != null);
Debug.Assert(trace != null); Debug.Assert(trace != null);
_socket = socket; _socket = socket;
PipeFactory = pipeFactory; BufferPool = bufferPool;
_trace = trace; _trace = trace;
var localEndPoint = (IPEndPoint)_socket.LocalEndPoint; var localEndPoint = (IPEndPoint)_socket.LocalEndPoint;
@ -48,7 +51,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
_sender = new SocketSender(_socket); _sender = new SocketSender(_socket);
} }
public override PipeFactory PipeFactory { get; } public override BufferPool BufferPool { get; }
public override IScheduler InputWriterScheduler => InlineScheduler.Default; public override IScheduler InputWriterScheduler => InlineScheduler.Default;
public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default; public override IScheduler OutputReaderScheduler => TaskRunScheduler.Default;

View File

@ -19,7 +19,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 ReceiveAsync(Buffer<byte> buffer) public SocketAwaitable ReceiveAsync(Memory<byte> buffer)
{ {
var segment = buffer.GetArray(); var segment = buffer.GetArray();
@ -33,4 +33,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
return _awaitable; return _awaitable;
} }
} }
} }

View File

@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
return _awaitable; return _awaitable;
} }
private SocketAwaitable SendAsync(Buffer<byte> buffer) private SocketAwaitable SendAsync(Memory<byte> buffer)
{ {
var segment = buffer.GetArray(); var segment = buffer.GetArray();
@ -95,4 +95,4 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
awaitable.Complete(e.BytesTransferred, e.SocketError); awaitable.Complete(e.BytesTransferred, e.SocketError);
} }
} }
} }

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.Diagnostics; using System.Diagnostics;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
@ -19,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
{ {
internal sealed class SocketTransport : ITransport internal sealed class SocketTransport : ITransport
{ {
private readonly PipeFactory _pipeFactory = new PipeFactory(); private readonly BufferPool _bufferPool = new MemoryPool();
private readonly IEndPointInformation _endPointInformation; private readonly IEndPointInformation _endPointInformation;
private readonly IConnectionHandler _handler; private readonly IConnectionHandler _handler;
private readonly IApplicationLifetime _appLifetime; private readonly IApplicationLifetime _appLifetime;
@ -115,7 +116,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
public Task StopAsync() public Task StopAsync()
{ {
_pipeFactory.Dispose(); _bufferPool.Dispose();
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -130,7 +131,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
var acceptSocket = await _listenSocket.AcceptAsync(); var acceptSocket = await _listenSocket.AcceptAsync();
acceptSocket.NoDelay = _endPointInformation.NoDelay; acceptSocket.NoDelay = _endPointInformation.NoDelay;
var connection = new SocketConnection(acceptSocket, _pipeFactory, _trace); var connection = new SocketConnection(acceptSocket, _bufferPool, _trace);
_ = connection.StartAsync(_handler); _ = connection.StartAsync(_handler);
} }
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionReset) catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionReset)

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -14,6 +15,6 @@ namespace Microsoft.AspNetCore.Protocols
public abstract IPipeConnection Transport { get; set; } public abstract IPipeConnection Transport { get; set; }
public abstract PipeFactory PipeFactory { get; } public abstract BufferPool BufferPool { get; }
} }
} }

View File

@ -1,4 +1,5 @@
using System.IO.Pipelines; using System.Buffers;
using System.IO.Pipelines;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Protocols.Features; using Microsoft.AspNetCore.Protocols.Features;
@ -27,7 +28,7 @@ namespace Microsoft.AspNetCore.Protocols
public override IFeatureCollection Features => _features.Collection; public override IFeatureCollection Features => _features.Collection;
public override PipeFactory PipeFactory => ConnectionTransportFeature.PipeFactory; public override BufferPool BufferPool => ConnectionTransportFeature.BufferPool;
public override IPipeConnection Transport public override IPipeConnection Transport
{ {

View File

@ -1,10 +1,12 @@
using System.IO.Pipelines; using System.Buffers;
using System.IO.Pipelines;
using System.Threading;
namespace Microsoft.AspNetCore.Protocols.Features namespace Microsoft.AspNetCore.Protocols.Features
{ {
public interface IConnectionTransportFeature public interface IConnectionTransportFeature
{ {
PipeFactory PipeFactory { get; } BufferPool BufferPool { get; }
IPipeConnection Transport { get; set; } IPipeConnection Transport { get; set; }

View File

@ -1,16 +1,18 @@
namespace System.IO.Pipelines using System.Buffers;
namespace System.IO.Pipelines
{ {
public static class PipeFactoryExtensions public static class PipeFactory
{ {
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(this PipeFactory pipeFactory) public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(BufferPool memoryPool)
{ {
return pipeFactory.CreateConnectionPair(new PipeOptions(), new PipeOptions()); return CreateConnectionPair(new PipeOptions(memoryPool), new PipeOptions(memoryPool));
} }
public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(this PipeFactory pipeFactory, PipeOptions inputOptions, PipeOptions outputOptions) public static (IPipeConnection Transport, IPipeConnection Application) CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions)
{ {
var input = pipeFactory.Create(inputOptions); var input = new Pipe(inputOptions);
var output = pipeFactory.Create(outputOptions); var output = new Pipe(outputOptions);
var transportToApplication = new PipeConnection(output.Reader, input.Writer); var transportToApplication = new PipeConnection(output.Reader, input.Writer);
var applicationToTransport = new PipeConnection(input.Reader, output.Writer); var applicationToTransport = new PipeConnection(input.Reader, output.Writer);

View File

@ -1,8 +1,10 @@
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Protocols.Features; using Microsoft.AspNetCore.Protocols.Features;
@ -51,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Set<IConnectionTransportFeature>(this); Set<IConnectionTransportFeature>(this);
} }
public PipeFactory PipeFactory { get; } = new PipeFactory(); public BufferPool BufferPool { get; } = new MemoryPool();
public IPipeConnection Transport { get; set; } public IPipeConnection Transport { get; set; }
public IPipeConnection Application { get; set; } public IPipeConnection Application { get; set; }

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.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -32,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private readonly TestHttp1Connection<object> _http1Connection; private readonly TestHttp1Connection<object> _http1Connection;
private readonly ServiceContext _serviceContext; private readonly ServiceContext _serviceContext;
private readonly Http1ConnectionContext _http1ConnectionContext; private readonly Http1ConnectionContext _http1ConnectionContext;
private readonly PipeFactory _pipelineFactory; private readonly BufferPool _pipelineFactory;
private ReadCursor _consumed; private ReadCursor _consumed;
private ReadCursor _examined; private ReadCursor _examined;
private Mock<ITimeoutControl> _timeoutControl; private Mock<ITimeoutControl> _timeoutControl;
@ -52,8 +53,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public Http1ConnectionTests() public Http1ConnectionTests()
{ {
_pipelineFactory = new PipeFactory(); _pipelineFactory = new MemoryPool();
var pair = _pipelineFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(_pipelineFactory);
_transport = pair.Transport; _transport = pair.Transport;
_application = pair.Application; _application = pair.Application;
@ -64,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
ServiceContext = _serviceContext, ServiceContext = _serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = _pipelineFactory, BufferPool = _pipelineFactory,
TimeoutControl = _timeoutControl.Object, TimeoutControl = _timeoutControl.Object,
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport Transport = pair.Transport

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.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -92,7 +93,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private static readonly byte[] _noData = new byte[0]; private static readonly byte[] _noData = new byte[0];
private static readonly byte[] _maxData = Encoding.ASCII.GetBytes(new string('a', Http2Frame.MinAllowedMaxFrameSize)); private static readonly byte[] _maxData = Encoding.ASCII.GetBytes(new string('a', Http2Frame.MinAllowedMaxFrameSize));
private readonly PipeFactory _pipeFactory = new PipeFactory(); private readonly BufferPool _bufferPool = new MemoryPool();
private readonly (IPipeConnection Transport, IPipeConnection Application) _pair; private readonly (IPipeConnection Transport, IPipeConnection Application) _pair;
private readonly TestApplicationErrorLogger _logger; private readonly TestApplicationErrorLogger _logger;
private readonly Http2ConnectionContext _connectionContext; private readonly Http2ConnectionContext _connectionContext;
@ -121,7 +122,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public Http2ConnectionTests() public Http2ConnectionTests()
{ {
_pair = _pipeFactory.CreateConnectionPair(); _pair = PipeFactory.CreateConnectionPair(_bufferPool);
_noopApplication = context => Task.CompletedTask; _noopApplication = context => Task.CompletedTask;
@ -256,7 +257,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
Log = new TestKestrelTrace(_logger) Log = new TestKestrelTrace(_logger)
}, },
PipeFactory = _pipeFactory, BufferPool = _bufferPool,
Application = _pair.Application, Application = _pair.Application,
Transport = _pair.Transport Transport = _pair.Transport
}; };
@ -265,7 +266,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void Dispose() public void Dispose()
{ {
_pipeFactory.Dispose(); _bufferPool.Dispose();
} }
void IHttpHeadersHandler.OnHeader(Span<byte> name, Span<byte> value) void IHttpHeadersHandler.OnHeader(Span<byte> name, Span<byte> value)

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.Collections.Generic; using System.Collections.Generic;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading; using System.Threading;
@ -17,21 +18,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
public class HttpConnectionTests : IDisposable public class HttpConnectionTests : IDisposable
{ {
private readonly PipeFactory _pipeFactory; private readonly BufferPool _bufferPool;
private readonly HttpConnectionContext _httpConnectionContext; private readonly HttpConnectionContext _httpConnectionContext;
private readonly HttpConnection _httpConnection; private readonly HttpConnection _httpConnection;
public HttpConnectionTests() public HttpConnectionTests()
{ {
_pipeFactory = new PipeFactory(); _bufferPool = new MemoryPool();
var pair = _pipeFactory.CreateConnectionPair(); var pair = PipeFactory.CreateConnectionPair(_bufferPool);
_httpConnectionContext = new HttpConnectionContext _httpConnectionContext = new HttpConnectionContext
{ {
ConnectionId = "0123456789", ConnectionId = "0123456789",
ConnectionAdapters = new List<IConnectionAdapter>(), ConnectionAdapters = new List<IConnectionAdapter>(),
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = _pipeFactory, BufferPool = _bufferPool,
HttpConnectionId = long.MinValue, HttpConnectionId = long.MinValue,
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport, Transport = pair.Transport,
@ -46,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void Dispose() public void Dispose()
{ {
_pipeFactory.Dispose(); _bufferPool.Dispose();
} }
[Fact] [Fact]

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.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO.Pipelines; using System.IO.Pipelines;
@ -19,26 +20,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact] [Fact]
public void InitialDictionaryIsEmpty() public void InitialDictionaryIsEmpty()
{ {
var factory = new PipeFactory(); using (var memoryPool = new MemoryPool())
var pair = factory.CreateConnectionPair();
var http1ConnectionContext = new Http1ConnectionContext
{ {
ServiceContext = new TestServiceContext(), var pair = PipeFactory.CreateConnectionPair(memoryPool);
ConnectionFeatures = new FeatureCollection(), var http1ConnectionContext = new Http1ConnectionContext
PipeFactory = factory, {
Application = pair.Application, ServiceContext = new TestServiceContext(),
Transport = pair.Transport, ConnectionFeatures = new FeatureCollection(),
TimeoutControl = null BufferPool = memoryPool,
}; Application = pair.Application,
Transport = pair.Transport,
TimeoutControl = null
};
var http1Connection = new Http1Connection<object>(application: null, context: http1ConnectionContext); var http1Connection = new Http1Connection<object>(application: null, context: http1ConnectionContext);
http1Connection.Reset(); http1Connection.Reset();
IDictionary<string, StringValues> headers = http1Connection.ResponseHeaders; IDictionary<string, StringValues> headers = http1Connection.ResponseHeaders;
Assert.Equal(0, headers.Count); Assert.Equal(0, headers.Count);
Assert.False(headers.IsReadOnly); Assert.False(headers.IsReadOnly);
}
} }
[Theory] [Theory]

View File

@ -21,6 +21,7 @@
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
<PackageReference Include="System.IO.Pipelines.Testing" Version="$(SystemIOPipelinesTestingPackageVersion)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -2,7 +2,9 @@
// 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.Threading;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
@ -13,25 +15,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
public class OutputProducerTests : IDisposable public class OutputProducerTests : IDisposable
{ {
private readonly PipeFactory _pipeFactory; private readonly BufferPool _bufferPool;
public OutputProducerTests() public OutputProducerTests()
{ {
_pipeFactory = new PipeFactory(); _bufferPool = new MemoryPool();
} }
public void Dispose() public void Dispose()
{ {
_pipeFactory.Dispose(); _bufferPool.Dispose();
} }
[Fact] [Fact]
public void WritesNoopAfterConnectionCloses() public void WritesNoopAfterConnectionCloses()
{ {
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = Mock.Of<IScheduler>(), bufferPool:_bufferPool,
}; readerScheduler: Mock.Of<IScheduler>()
);
using (var socketOutput = CreateOutputProducer(pipeOptions)) using (var socketOutput = CreateOutputProducer(pipeOptions))
{ {
@ -52,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private Http1OutputProducer CreateOutputProducer(PipeOptions pipeOptions) private Http1OutputProducer CreateOutputProducer(PipeOptions pipeOptions)
{ {
var pipe = _pipeFactory.Create(pipeOptions); var pipe = new Pipe(pipeOptions);
var serviceContext = new TestServiceContext(); var serviceContext = new TestServiceContext();
var socketOutput = new Http1OutputProducer( var socketOutput = new Http1OutputProducer(
pipe.Reader, pipe.Reader,

View File

@ -1,8 +1,10 @@
// 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.Generic; using System.Collections.Generic;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
@ -25,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
serviceContext.ThreadPool = new LoggingThreadPool(null); serviceContext.ThreadPool = new LoggingThreadPool(null);
var mockScheduler = Mock.Of<IScheduler>(); var mockScheduler = Mock.Of<IScheduler>();
var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, readerScheduler: mockScheduler); var outputPipeOptions = ConnectionHandler.GetOutputPipeOptions(serviceContext, new MemoryPool(), readerScheduler: mockScheduler);
Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow); Assert.Equal(expectedMaximumSizeLow, outputPipeOptions.MaximumSizeLow);
Assert.Equal(expectedMaximumSizeHigh, outputPipeOptions.MaximumSizeHigh); Assert.Equal(expectedMaximumSizeHigh, outputPipeOptions.MaximumSizeHigh);
@ -43,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
serviceContext.ThreadPool = new LoggingThreadPool(null); serviceContext.ThreadPool = new LoggingThreadPool(null);
var mockScheduler = Mock.Of<IScheduler>(); var mockScheduler = Mock.Of<IScheduler>();
var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, writerScheduler: mockScheduler); var inputPipeOptions = ConnectionHandler.GetInputPipeOptions(serviceContext, new MemoryPool(), writerScheduler: mockScheduler);
Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow); Assert.Equal(expectedMaximumSizeLow, inputPipeOptions.MaximumSizeLow);
Assert.Equal(expectedMaximumSizeHigh, inputPipeOptions.MaximumSizeHigh); Assert.Equal(expectedMaximumSizeHigh, inputPipeOptions.MaximumSizeHigh);

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.Text; using System.Text;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
@ -15,16 +16,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private const int _ulongMaxValueLength = 20; private const int _ulongMaxValueLength = 20;
private readonly IPipe _pipe; private readonly IPipe _pipe;
private readonly PipeFactory _pipeFactory = new PipeFactory(); private readonly BufferPool _bufferPool = new MemoryPool();
public PipelineExtensionTests() public PipelineExtensionTests()
{ {
_pipe = _pipeFactory.Create(); _pipe = new Pipe(new PipeOptions(_bufferPool));
} }
public void Dispose() public void Dispose()
{ {
_pipeFactory.Dispose(); _bufferPool.Dispose();
} }
[Theory] [Theory]
@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
var writerBuffer = _pipe.Writer.Alloc(); var writerBuffer = _pipe.Writer.Alloc();
var writer = new WritableBufferWriter(writerBuffer); var writer = new WritableBufferWriter(writerBuffer);
PipelineExtensions.WriteNumeric(ref writer, number); writer.WriteNumeric(number);
writerBuffer.FlushAsync().GetAwaiter().GetResult(); writerBuffer.FlushAsync().GetAwaiter().GetResult();
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
@ -57,7 +58,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
writer.Write(spacer); writer.Write(spacer);
var bufferLength = writer.Span.Length; var bufferLength = writer.Span.Length;
PipelineExtensions.WriteNumeric(ref writer, ulong.MaxValue); writer.WriteNumeric(ulong.MaxValue);
Assert.NotEqual(bufferLength, writer.Span.Length); Assert.NotEqual(bufferLength, writer.Span.Length);
writerBuffer.FlushAsync().GetAwaiter().GetResult(); writerBuffer.FlushAsync().GetAwaiter().GetResult();
@ -83,7 +84,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{ {
var writerBuffer = _pipe.Writer.Alloc(); var writerBuffer = _pipe.Writer.Alloc();
var writer = new WritableBufferWriter(writerBuffer); var writer = new WritableBufferWriter(writerBuffer);
PipelineExtensions.WriteAsciiNoValidation(ref writer, input); writer.WriteAsciiNoValidation(input);
writerBuffer.FlushAsync().GetAwaiter().GetResult(); writerBuffer.FlushAsync().GetAwaiter().GetResult();
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
@ -110,7 +111,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// but it shouldn't produce more than one byte per character // but it shouldn't produce more than one byte per character
var writerBuffer = _pipe.Writer.Alloc(); var writerBuffer = _pipe.Writer.Alloc();
var writer = new WritableBufferWriter(writerBuffer); var writer = new WritableBufferWriter(writerBuffer);
PipelineExtensions.WriteAsciiNoValidation(ref writer, input); writer.WriteAsciiNoValidation(input);
writerBuffer.FlushAsync().GetAwaiter().GetResult(); writerBuffer.FlushAsync().GetAwaiter().GetResult();
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
@ -125,7 +126,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var writer = new WritableBufferWriter(writerBuffer); var writer = new WritableBufferWriter(writerBuffer);
for (var i = 0; i < maxAscii; i++) for (var i = 0; i < maxAscii; i++)
{ {
PipelineExtensions.WriteAsciiNoValidation(ref writer, new string((char)i, 1)); writer.WriteAsciiNoValidation(new string((char)i, 1));
} }
writerBuffer.FlushAsync().GetAwaiter().GetResult(); writerBuffer.FlushAsync().GetAwaiter().GetResult();
@ -158,7 +159,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(gapSize, writer.Span.Length); Assert.Equal(gapSize, writer.Span.Length);
var bufferLength = writer.Span.Length; var bufferLength = writer.Span.Length;
PipelineExtensions.WriteAsciiNoValidation(ref writer, testString); writer.WriteAsciiNoValidation(testString);
Assert.NotEqual(bufferLength, writer.Span.Length); Assert.NotEqual(bufferLength, writer.Span.Length);
writerBuffer.FlushAsync().GetAwaiter().GetResult(); writerBuffer.FlushAsync().GetAwaiter().GetResult();

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.Text; using System.Text;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -15,13 +16,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
class TestInput : IDisposable class TestInput : IDisposable
{ {
private MemoryPool _memoryPool; private MemoryPool _memoryPool;
private PipeFactory _pipelineFactory;
public TestInput() public TestInput()
{ {
_memoryPool = new MemoryPool(); _memoryPool = new MemoryPool();
_pipelineFactory = new PipeFactory(); var pair = PipeFactory.CreateConnectionPair(_memoryPool);
var pair = _pipelineFactory.CreateConnectionPair();
Transport = pair.Transport; Transport = pair.Transport;
Application = pair.Application; Application = pair.Application;
@ -31,7 +30,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
Application = Application, Application = Application,
Transport = Transport, Transport = Transport,
PipeFactory = _pipelineFactory, BufferPool = _memoryPool,
TimeoutControl = Mock.Of<ITimeoutControl>() TimeoutControl = Mock.Of<ITimeoutControl>()
}; };
@ -43,8 +42,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public IPipeConnection Application { get; } public IPipeConnection Application { get; }
public PipeFactory PipeFactory => _pipelineFactory;
public Http1ConnectionContext Http1ConnectionContext { get; } public Http1ConnectionContext Http1ConnectionContext { get; }
public Http1Connection Http1Connection { get; set; } public Http1Connection Http1Connection { get; set; }
@ -67,7 +64,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void Dispose() public void Dispose()
{ {
_pipelineFactory.Dispose();
_memoryPool.Dispose(); _memoryPool.Dispose();
} }
} }

View File

@ -55,13 +55,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied() public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied()
{ {
var mockConnectionHandler = new MockConnectionHandler(); var mockConnectionHandler = new MockConnectionHandler();
mockConnectionHandler.InputOptions.MaximumSizeHigh = 3;
var mockLibuv = new MockLibuv(); var mockLibuv = new MockLibuv();
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);
mockConnectionHandler.InputOptions = pool =>
new PipeOptions(
bufferPool: pool,
maximumSizeHigh: 3);
// We don't set the output writer scheduler here since we want to run the callback inline // We don't set the output writer scheduler here since we want to run the callback inline
mockConnectionHandler.OutputOptions.ReaderScheduler = thread;
mockConnectionHandler.OutputOptions = pool => new PipeOptions(bufferPool: pool, readerScheduler: thread);
Task connectionTask = null; Task connectionTask = null;
try try
{ {
@ -106,8 +113,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
public async Task ConnectionDoesNotResumeAfterReadCallbackScheduledAndSocketCloseIfBackpressureIsApplied() public async Task ConnectionDoesNotResumeAfterReadCallbackScheduledAndSocketCloseIfBackpressureIsApplied()
{ {
var mockConnectionHandler = new MockConnectionHandler(); var mockConnectionHandler = new MockConnectionHandler();
mockConnectionHandler.InputOptions.MaximumSizeHigh = 3;
mockConnectionHandler.InputOptions.MaximumSizeLow = 3;
var mockLibuv = new MockLibuv(); var mockLibuv = new MockLibuv();
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);
@ -118,8 +123,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
{ {
backPressure = () => a(o); backPressure = () => a(o);
}); });
mockConnectionHandler.InputOptions.WriterScheduler = mockScheduler.Object; mockConnectionHandler.InputOptions = pool =>
mockConnectionHandler.OutputOptions.ReaderScheduler = thread; new PipeOptions(
bufferPool: pool,
maximumSizeHigh: 3,
maximumSizeLow: 3,
writerScheduler: mockScheduler.Object);
mockConnectionHandler.OutputOptions = pool => new PipeOptions(bufferPool: pool, readerScheduler:thread );
Task connectionTask = null; Task connectionTask = null;
try try
{ {

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.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Threading; using System.Threading;
@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
{ {
public class LibuvOutputConsumerTests : IDisposable public class LibuvOutputConsumerTests : IDisposable
{ {
private readonly PipeFactory _pipeFactory; private readonly BufferPool _bufferPool;
private readonly MockLibuv _mockLibuv; private readonly MockLibuv _mockLibuv;
private readonly LibuvThread _libuvThread; private readonly LibuvThread _libuvThread;
@ -37,7 +38,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
public LibuvOutputConsumerTests() public LibuvOutputConsumerTests()
{ {
_pipeFactory = new PipeFactory(); _bufferPool = new MemoryPool();
_mockLibuv = new MockLibuv(); _mockLibuv = new MockLibuv();
var libuvTransport = new LibuvTransport(_mockLibuv, new TestLibuvTransportContext(), new ListenOptions(0)); var libuvTransport = new LibuvTransport(_mockLibuv, new TestLibuvTransportContext(), new ListenOptions(0));
@ -48,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
public void Dispose() public void Dispose()
{ {
_libuvThread.StopAsync(TimeSpan.FromSeconds(1)).Wait(); _libuvThread.StopAsync(TimeSpan.FromSeconds(1)).Wait();
_pipeFactory.Dispose(); _bufferPool.Dispose();
} }
[Theory] [Theory]
@ -62,11 +63,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null. // ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly. // This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize ?? 0, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize ?? 0, maximumSizeHigh: maxResponseBufferSize ?? 0,
}; maximumSizeLow: maxResponseBufferSize ?? 0
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -97,11 +99,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null. // ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly. // This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = 0, readerScheduler: _libuvThread,
MaximumSizeLow = 0, maximumSizeHigh: 0,
}; maximumSizeLow: 0
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -144,11 +147,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
// ConnectionHandler will set MaximumSizeHigh/Low to 1 when MaxResponseBufferSize is zero. // ConnectionHandler will set MaximumSizeHigh/Low to 1 when MaxResponseBufferSize is zero.
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly. // This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = 1, readerScheduler: _libuvThread,
MaximumSizeLow = 1, maximumSizeHigh: 1,
}; maximumSizeLow: 1
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -199,11 +203,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
}; };
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize, maximumSizeHigh: maxResponseBufferSize,
}; maximumSizeLow: maxResponseBufferSize
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -262,11 +267,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
}; };
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize, maximumSizeHigh: maxResponseBufferSize,
}; maximumSizeLow: maxResponseBufferSize
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -331,11 +337,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
var abortedSource = new CancellationTokenSource(); var abortedSource = new CancellationTokenSource();
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize, maximumSizeHigh: maxResponseBufferSize,
}; maximumSizeLow: maxResponseBufferSize
);
using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource)) using (var outputProducer = CreateOutputProducer(pipeOptions, abortedSource))
{ {
@ -423,11 +430,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
var abortedSource = new CancellationTokenSource(); var abortedSource = new CancellationTokenSource();
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize, maximumSizeHigh: maxResponseBufferSize,
}; maximumSizeLow: maxResponseBufferSize
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -506,11 +514,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
var abortedSource = new CancellationTokenSource(); var abortedSource = new CancellationTokenSource();
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize, maximumSizeHigh: maxResponseBufferSize,
}; maximumSizeLow: maxResponseBufferSize
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -587,11 +596,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
}; };
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize, maximumSizeHigh: maxResponseBufferSize,
}; maximumSizeLow: maxResponseBufferSize
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -647,11 +657,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
// ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null. // ConnectionHandler will set MaximumSizeHigh/Low to zero when MaxResponseBufferSize is null.
// This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly. // This is verified in PipeOptionsTests.OutputPipeOptionsConfiguredCorrectly.
var pipeOptions = new PipeOptions var pipeOptions = new PipeOptions
{ (
ReaderScheduler = _libuvThread, bufferPool: _bufferPool,
MaximumSizeHigh = maxResponseBufferSize ?? 0, readerScheduler: _libuvThread,
MaximumSizeLow = maxResponseBufferSize ?? 0, maximumSizeHigh: maxResponseBufferSize ?? 0,
}; maximumSizeLow: maxResponseBufferSize ?? 0
);
using (var outputProducer = CreateOutputProducer(pipeOptions)) using (var outputProducer = CreateOutputProducer(pipeOptions))
{ {
@ -684,7 +695,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
private Http1OutputProducer CreateOutputProducer(PipeOptions pipeOptions, CancellationTokenSource cts = null) private Http1OutputProducer CreateOutputProducer(PipeOptions pipeOptions, CancellationTokenSource cts = null)
{ {
var pair = _pipeFactory.CreateConnectionPair(pipeOptions, pipeOptions); var pair = PipeFactory.CreateConnectionPair(pipeOptions, pipeOptions);
var logger = new TestApplicationErrorLogger(); var logger = new TestApplicationErrorLogger();
var serviceContext = new TestServiceContext var serviceContext = new TestServiceContext
@ -701,7 +712,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
{ {
ServiceContext = serviceContext, ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(), ConnectionFeatures = new FeatureCollection(),
PipeFactory = _pipeFactory, BufferPool = _bufferPool,
TimeoutControl = Mock.Of<ITimeoutControl>(), TimeoutControl = Mock.Of<ITimeoutControl>(),
Application = pair.Application, Application = pair.Application,
Transport = pair.Transport Transport = pair.Transport

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.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -13,15 +14,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
{ {
public class MockConnectionHandler : IConnectionHandler public class MockConnectionHandler : IConnectionHandler
{ {
public PipeOptions InputOptions { get; set; } = new PipeOptions(); public Func<BufferPool, PipeOptions> InputOptions { get; set; } = pool => new PipeOptions(pool);
public PipeOptions OutputOptions { get; set; } = new PipeOptions(); public Func<BufferPool, PipeOptions> OutputOptions { get; set; } = pool => new PipeOptions(pool);
public void OnConnection(IFeatureCollection features) public void OnConnection(IFeatureCollection features)
{ {
var connectionContext = new DefaultConnectionContext(features); var connectionContext = new DefaultConnectionContext(features);
Input = connectionContext.PipeFactory.Create(InputOptions ?? new PipeOptions()); Input = new Pipe(InputOptions(connectionContext.BufferPool));
Output = connectionContext.PipeFactory.Create(OutputOptions ?? new PipeOptions()); Output = new Pipe(InputOptions(connectionContext.BufferPool));
var feature = connectionContext.Features.Get<IConnectionTransportFeature>(); var feature = connectionContext.Features.Get<IConnectionTransportFeature>();