Add benchmarks for Frame writes.

This commit is contained in:
Cesar Blum Silveira 2016-12-07 17:34:01 -08:00
parent f467c42f54
commit 51ecbd7949
8 changed files with 162 additions and 18 deletions

View File

@ -39,10 +39,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0EF2AC
test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs
test\shared\MockConnection.cs = test\shared\MockConnection.cs test\shared\MockConnection.cs = test\shared\MockConnection.cs
test\shared\MockFrameControl.cs = test\shared\MockFrameControl.cs test\shared\MockFrameControl.cs = test\shared\MockFrameControl.cs
test\shared\MockSocketOutput.cs = test\shared\MockSocketOutput.cs
test\shared\MockSystemClock.cs = test\shared\MockSystemClock.cs test\shared\MockSystemClock.cs = test\shared\MockSystemClock.cs
test\shared\SocketInputExtensions.cs = test\shared\SocketInputExtensions.cs test\shared\SocketInputExtensions.cs = test\shared\SocketInputExtensions.cs
test\shared\TestApplicationErrorLogger.cs = test\shared\TestApplicationErrorLogger.cs test\shared\TestApplicationErrorLogger.cs = test\shared\TestApplicationErrorLogger.cs
test\shared\TestConnection.cs = test\shared\TestConnection.cs test\shared\TestConnection.cs = test\shared\TestConnection.cs
test\shared\TestFrame.cs = test\shared\TestFrame.cs
test\shared\TestKestrelTrace.cs = test\shared\TestKestrelTrace.cs test\shared\TestKestrelTrace.cs = test\shared\TestKestrelTrace.cs
test\shared\TestServer.cs = test\shared\TestServer.cs test\shared\TestServer.cs = test\shared\TestServer.cs
test\shared\TestServiceContext.cs = test\shared\TestServiceContext.cs test\shared\TestServiceContext.cs = test\shared\TestServiceContext.cs

View File

@ -2,11 +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 BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Properties;
using BenchmarkDotNet.Running; using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
@ -36,6 +32,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
BenchmarkRunner.Run<RequestParsing>(); BenchmarkRunner.Run<RequestParsing>();
} }
if (type.HasFlag(BenchmarkType.Writing))
{
BenchmarkRunner.Run<Writing>();
}
} }
} }
@ -43,6 +43,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public enum BenchmarkType : uint public enum BenchmarkType : uint
{ {
RequestParsing = 1, RequestParsing = 1,
Writing = 2,
// add new ones in powers of two - e.g. 2,4,8,16... // add new ones in powers of two - e.g. 2,4,8,16...
All = uint.MaxValue All = uint.MaxValue

View File

@ -2,10 +2,10 @@
To run a specific benchmark add it as parameter To run a specific benchmark add it as parameter
``` ```
dotnet run RequestParsing dotnet run -c Release RequestParsing
``` ```
To run all use `All` as parameter To run all use `All` as parameter
``` ```
dotnet run All dotnet run -c Release All
``` ```
Using no parameter will list all available benchmarks Using no parameter will list all available benchmarks

View File

@ -0,0 +1,117 @@
// 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.
using System;
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Testing;
using Moq;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class Writing
{
private readonly TestFrame<object> _frame;
private readonly TestFrame<object> _frameChunked;
private readonly byte[] _writeData;
public Writing()
{
_frame = MakeFrame();
_frameChunked = MakeFrame();
_writeData = new byte[1];
}
[Setup]
public void Setup()
{
_frame.Reset();
_frame.RequestHeaders.Add("Content-Length", "1073741824");
_frameChunked.Reset();
_frameChunked.RequestHeaders.Add("Transfer-Encoding", "chunked");
}
[Benchmark]
public void Write()
{
_frame.Write(new ArraySegment<byte>(_writeData));
}
[Benchmark]
public void WriteChunked()
{
_frameChunked.Write(new ArraySegment<byte>(_writeData));
}
[Benchmark]
public async Task WriteAsync()
{
await _frame.WriteAsync(new ArraySegment<byte>(_writeData), default(CancellationToken));
}
[Benchmark]
public async Task WriteAsyncChunked()
{
await _frameChunked.WriteAsync(new ArraySegment<byte>(_writeData), default(CancellationToken));
}
[Benchmark]
public async Task WriteAsyncAwaited()
{
await _frame.WriteAsyncAwaited(new ArraySegment<byte>(_writeData), default(CancellationToken));
}
[Benchmark]
public async Task WriteAsyncAwaitedChunked()
{
await _frameChunked.WriteAsyncAwaited(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 ltp = new LoggingThreadPool(Mock.Of<IKestrelTrace>());
var pool = new MemoryPool();
var socketInput = new SocketInput(pool, ltp);
var serviceContext = new ServiceContext
{
DateHeaderValueManager = new DateHeaderValueManager(),
ServerOptions = new KestrelServerOptions(),
Log = Mock.Of<IKestrelTrace>()
};
var listenerContext = new ListenerContext(serviceContext)
{
ServerAddress = ServerAddress.FromUrl("http://localhost:5000")
};
var connectionContext = new ConnectionContext(listenerContext)
{
Input = socketInput,
Output = new MockSocketOutput(),
ConnectionControl = Mock.Of<IConnectionControl>()
};
var frame = new TestFrame<object>(application: null, context: connectionContext);
frame.Reset();
frame.InitializeHeaders();
return frame;
}
}
}

View File

@ -1,14 +1,15 @@
{ {
"version": "1.0.0-*", "version": "1.0.0-*",
"dependencies": { "dependencies": {
"BenchmarkDotNet": "0.10.0", "BenchmarkDotNet": "0.10.1",
"Microsoft.AspNetCore.Server.Kestrel": "1.2.0-*" "Microsoft.AspNetCore.Server.Kestrel": "1.2.0-*",
"Moq": "4.6.36-*"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.1": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": { "Microsoft.NETCore.App": {
"version": "1.0.1-*", "version": "1.1.0-*",
"type": "platform" "type": "platform"
} }
} }
@ -18,16 +19,18 @@
"emitEntryPoint": true, "emitEntryPoint": true,
"compile": { "compile": {
"include": [ "include": [
"../shared/SocketInputExtensions.cs",
"../shared/TestKestrelTrace.cs",
"../shared/TestApplicationErrorLogger.cs", "../shared/TestApplicationErrorLogger.cs",
"../shared/MockConnection.cs" "../shared/TestFrame.cs",
"../shared/TestKestrelTrace.cs",
"../shared/MockConnection.cs",
"../shared/MockSocketOutput.cs",
"../shared/SocketInputExtensions.cs"
] ]
}, },
"keyFile": "../../tools/Key.snk", "keyFile": "../../tools/Key.snk",
"copyToOutput": { "copyToOutput": {
"include": "TestResources/testCert.pfx" "include": "TestResources/testCert.pfx"
} },
}, },
"runtimeOptions": { "runtimeOptions": {
"configProperties": { "configProperties": {

View File

@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Server.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Internal; using Microsoft.AspNetCore.Server.Kestrel.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Moq; using Moq;
@ -47,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
_connectionContext = new ConnectionContext(listenerContext) _connectionContext = new ConnectionContext(listenerContext)
{ {
Input = _socketInput, Input = _socketInput,
Output = new MockSocketOuptut(), Output = new MockSocketOutput(),
ConnectionControl = Mock.Of<IConnectionControl>() ConnectionControl = Mock.Of<IConnectionControl>()
}; };

View File

@ -8,9 +8,9 @@ using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers namespace Microsoft.AspNetCore.Testing
{ {
public class MockSocketOuptut : ISocketOutput public class MockSocketOutput : ISocketOutput
{ {
public void ProducingComplete(MemoryPoolIterator end) public void ProducingComplete(MemoryPoolIterator end)
{ {

22
test/shared/TestFrame.cs Normal file
View File

@ -0,0 +1,22 @@
// 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.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
namespace Microsoft.AspNetCore.Testing
{
public class TestFrame<TContext> : Frame<TContext>
{
public TestFrame(IHttpApplication<TContext> application, ConnectionContext context)
: base(application, context)
{
}
public Task ProduceEndAsync()
{
return ProduceEnd();
}
}
}