Measure Writing in FrameWritingBenchmark
This commit is contained in:
parent
442ee80039
commit
14f122fb9f
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
|
|
@ -16,68 +17,85 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
[Config(typeof(CoreConfig))]
|
[Config(typeof(CoreConfig))]
|
||||||
public class FrameWritingBenchmark
|
public class FrameWritingBenchmark
|
||||||
{
|
{
|
||||||
|
// Standard completed task
|
||||||
|
private static readonly Func<object, Task> _syncTaskFunc = (obj) => Task.CompletedTask;
|
||||||
|
// Non-standard completed task
|
||||||
|
private static readonly Task _psuedoAsyncTask = Task.FromResult(27);
|
||||||
|
private static readonly Func<object, Task> _psuedoAsyncTaskFunc = (obj) => _psuedoAsyncTask;
|
||||||
|
|
||||||
private readonly TestFrame<object> _frame;
|
private readonly TestFrame<object> _frame;
|
||||||
private readonly TestFrame<object> _frameChunked;
|
private readonly IPipe _outputPipe;
|
||||||
|
|
||||||
private readonly byte[] _writeData;
|
private readonly byte[] _writeData;
|
||||||
|
|
||||||
public FrameWritingBenchmark()
|
public FrameWritingBenchmark()
|
||||||
{
|
{
|
||||||
_frame = MakeFrame();
|
var pipeFactory = new PipeFactory();
|
||||||
_frameChunked = MakeFrame();
|
|
||||||
_writeData = new byte[1];
|
_outputPipe = pipeFactory.Create();
|
||||||
|
_frame = MakeFrame(pipeFactory);
|
||||||
|
_writeData = Encoding.ASCII.GetBytes("Hello, World!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Params(true, false)]
|
||||||
|
public bool WithHeaders { get; set; }
|
||||||
|
|
||||||
|
[Params(true, false)]
|
||||||
|
public bool Chunked { get; set; }
|
||||||
|
|
||||||
|
[Params(Startup.None, Startup.Sync, Startup.Async)]
|
||||||
|
public Startup OnStarting { get; set; }
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_frame.Reset();
|
_frame.Reset();
|
||||||
_frame.RequestHeaders.Add("Content-Length", "1073741824");
|
if (Chunked)
|
||||||
|
{
|
||||||
|
_frame.RequestHeaders.Add("Transfer-Encoding", "chunked");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_frame.RequestHeaders.ContentLength = _writeData.Length;
|
||||||
|
}
|
||||||
|
|
||||||
_frameChunked.Reset();
|
if (!WithHeaders)
|
||||||
_frameChunked.RequestHeaders.Add("Transfer-Encoding", "chunked");
|
{
|
||||||
|
_frame.FlushAsync().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetState()
|
||||||
|
{
|
||||||
|
if (WithHeaders)
|
||||||
|
{
|
||||||
|
_frame.ResetState();
|
||||||
|
|
||||||
|
switch (OnStarting)
|
||||||
|
{
|
||||||
|
case Startup.Sync:
|
||||||
|
_frame.OnStarting(_syncTaskFunc, null);
|
||||||
|
break;
|
||||||
|
case Startup.Async:
|
||||||
|
_frame.OnStarting(_psuedoAsyncTaskFunc, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public async Task WriteAsync()
|
public Task WriteAsync()
|
||||||
{
|
{
|
||||||
await _frame.WriteAsync(new ArraySegment<byte>(_writeData), default(CancellationToken));
|
ResetState();
|
||||||
|
|
||||||
|
return _frame.ResponseBody.WriteAsync(_writeData, 0, _writeData.Length, default(CancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
private TestFrame<object> MakeFrame(PipeFactory pipeFactory)
|
||||||
public async Task WriteAsyncChunked()
|
|
||||||
{
|
{
|
||||||
await _frameChunked.WriteAsync(new ArraySegment<byte>(_writeData), default(CancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public async Task WriteAsyncAwaited()
|
|
||||||
{
|
|
||||||
await _frame.WriteAsyncAwaited(Task.CompletedTask, new ArraySegment<byte>(_writeData), default(CancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public async Task WriteAsyncAwaitedChunked()
|
|
||||||
{
|
|
||||||
await _frameChunked.WriteAsyncAwaited(Task.CompletedTask, new ArraySegment<byte>(_writeData), default(CancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public async Task ProduceEnd()
|
|
||||||
{
|
|
||||||
await _frame.ProduceEndAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public async Task ProduceEndChunked()
|
|
||||||
{
|
|
||||||
await _frameChunked.ProduceEndAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TestFrame<object> MakeFrame()
|
|
||||||
{
|
|
||||||
var pipeFactory = new PipeFactory();
|
|
||||||
var input = pipeFactory.Create();
|
var input = pipeFactory.Create();
|
||||||
var output = pipeFactory.Create();
|
|
||||||
|
|
||||||
var serviceContext = new ServiceContext
|
var serviceContext = new ServiceContext
|
||||||
{
|
{
|
||||||
|
|
@ -92,12 +110,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||||
ServiceContext = serviceContext,
|
ServiceContext = serviceContext,
|
||||||
PipeFactory = pipeFactory,
|
PipeFactory = pipeFactory,
|
||||||
Input = input.Reader,
|
Input = input.Reader,
|
||||||
Output = output
|
Output = _outputPipe
|
||||||
});
|
});
|
||||||
|
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
|
frame.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Cleanup]
|
||||||
|
public void Cleanup()
|
||||||
|
{
|
||||||
|
var reader = _outputPipe.Reader;
|
||||||
|
if (reader.TryRead(out var readResult))
|
||||||
|
{
|
||||||
|
reader.Advance(readResult.Buffer.End);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Startup
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Sync,
|
||||||
|
Async
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
|
|
||||||
public void StopStreams() => _frameStreams.Stop();
|
public void StopStreams() => _frameStreams.Stop();
|
||||||
|
|
||||||
|
// For testing
|
||||||
|
internal void ResetState()
|
||||||
|
{
|
||||||
|
_requestProcessingStatus = RequestProcessingStatus.RequestPending;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
_onStarting = null;
|
_onStarting = null;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
||||||
private static readonly MessageBody _zeroContentLengthClose = new ForZeroContentLength(keepAlive: false);
|
private static readonly MessageBody _zeroContentLengthClose = new ForZeroContentLength(keepAlive: false);
|
||||||
private static readonly MessageBody _zeroContentLengthKeepAlive = new ForZeroContentLength(keepAlive: true);
|
private static readonly MessageBody _zeroContentLengthKeepAlive = new ForZeroContentLength(keepAlive: true);
|
||||||
|
|
||||||
|
// For testing
|
||||||
|
internal static MessageBody ZeroContentLengthKeepAlive => _zeroContentLengthKeepAlive;
|
||||||
|
|
||||||
private readonly Frame _context;
|
private readonly Frame _context;
|
||||||
|
|
||||||
private bool _send100Continue = true;
|
private bool _send100Continue = true;
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@ using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Core.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Core.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Kestrel.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue