Measure Writing in FrameWritingBenchmark
This commit is contained in:
parent
442ee80039
commit
14f122fb9f
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.IO.Pipelines;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
|
@ -16,68 +17,85 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
[Config(typeof(CoreConfig))]
|
||||
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> _frameChunked;
|
||||
private readonly IPipe _outputPipe;
|
||||
|
||||
private readonly byte[] _writeData;
|
||||
|
||||
public FrameWritingBenchmark()
|
||||
{
|
||||
_frame = MakeFrame();
|
||||
_frameChunked = MakeFrame();
|
||||
_writeData = new byte[1];
|
||||
var pipeFactory = new PipeFactory();
|
||||
|
||||
_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]
|
||||
public void Setup()
|
||||
{
|
||||
_frame.Reset();
|
||||
_frame.RequestHeaders.Add("Content-Length", "1073741824");
|
||||
if (Chunked)
|
||||
{
|
||||
_frame.RequestHeaders.Add("Transfer-Encoding", "chunked");
|
||||
}
|
||||
else
|
||||
{
|
||||
_frame.RequestHeaders.ContentLength = _writeData.Length;
|
||||
}
|
||||
|
||||
_frameChunked.Reset();
|
||||
_frameChunked.RequestHeaders.Add("Transfer-Encoding", "chunked");
|
||||
if (!WithHeaders)
|
||||
{
|
||||
_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]
|
||||
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]
|
||||
public async Task WriteAsyncChunked()
|
||||
private TestFrame<object> MakeFrame(PipeFactory pipeFactory)
|
||||
{
|
||||
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 output = pipeFactory.Create();
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
|
|
@ -92,12 +110,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
ServiceContext = serviceContext,
|
||||
PipeFactory = pipeFactory,
|
||||
Input = input.Reader,
|
||||
Output = output
|
||||
Output = _outputPipe
|
||||
});
|
||||
|
||||
frame.Reset();
|
||||
frame.InitializeStreams(MessageBody.ZeroContentLengthKeepAlive);
|
||||
|
||||
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();
|
||||
|
||||
// For testing
|
||||
internal void ResetState()
|
||||
{
|
||||
_requestProcessingStatus = RequestProcessingStatus.RequestPending;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_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 _zeroContentLengthKeepAlive = new ForZeroContentLength(keepAlive: true);
|
||||
|
||||
// For testing
|
||||
internal static MessageBody ZeroContentLengthKeepAlive => _zeroContentLengthKeepAlive;
|
||||
|
||||
private readonly Frame _context;
|
||||
|
||||
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.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")]
|
||||
|
|
|
|||
Loading…
Reference in New Issue