FrameFeatureCollection benchmark (#1643)

This commit is contained in:
Ben Adams 2017-04-10 00:02:18 +01:00 committed by David Fowler
parent fb22629da6
commit 2863cca8ca
5 changed files with 168 additions and 53 deletions

View File

@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_currentIHttpSendFileFeature = null;
}
private object FastFeatureGet(Type key)
internal object FastFeatureGet(Type key)
{
if (key == IHttpRequestFeatureType)
{
@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return ExtraFeatureGet(key);
}
private void FastFeatureSet(Type key, object feature)
internal void FastFeatureSet(Type key, object feature)
{
_featureRevision++;

View File

@ -0,0 +1,107 @@
// 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 BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
[Config(typeof(CoreConfig))]
public class FrameFeatureCollection
{
private readonly Frame<object> _frame;
private IFeatureCollection _collection;
[Benchmark(Baseline = true)]
public IHttpRequestFeature GetFirstViaFastFeature()
{
return (IHttpRequestFeature)GetFastFeature(typeof(IHttpRequestFeature));
}
[Benchmark]
public IHttpRequestFeature GetFirstViaType()
{
return (IHttpRequestFeature)Get(typeof(IHttpRequestFeature));
}
[Benchmark]
public IHttpRequestFeature GetFirstViaExtension()
{
return _collection.GetType<IHttpRequestFeature>();
}
[Benchmark]
public IHttpRequestFeature GetFirstViaGeneric()
{
return _collection.Get<IHttpRequestFeature>();
}
[Benchmark]
public IHttpSendFileFeature GetLastViaFastFeature()
{
return (IHttpSendFileFeature)GetFastFeature(typeof(IHttpSendFileFeature));
}
[Benchmark]
public IHttpSendFileFeature GetLastViaType()
{
return (IHttpSendFileFeature)Get(typeof(IHttpSendFileFeature));
}
[Benchmark]
public IHttpSendFileFeature GetLastViaExtension()
{
return _collection.GetType<IHttpSendFileFeature>();
}
[Benchmark]
public IHttpSendFileFeature GetLastViaGeneric()
{
return _collection.Get<IHttpSendFileFeature> ();
}
private object Get(Type type)
{
return _collection[type];
}
private object GetFastFeature(Type type)
{
return _frame.FastFeatureGet(type);
}
public FrameFeatureCollection()
{
var serviceContext = new ServiceContext
{
HttpParserFactory = _ => NullParser.Instance,
ServerOptions = new KestrelServerOptions()
};
var frameContext = new FrameContext
{
ServiceContext = serviceContext,
ConnectionInformation = new MockConnectionInformation()
};
_frame = new Frame<object>(application: null, frameContext: frameContext);
}
[Setup]
public void Setup()
{
_collection = _frame;
}
}
public static class IFeatureCollectionExtensions
{
public static T GetType<T>(this IFeatureCollection collection)
{
return (T)collection[typeof(T)];
}
}
}

View File

@ -1,12 +1,10 @@
// 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.Text;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
@ -100,52 +98,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
ErrorUtilities.ThrowInvalidRequestHeaders();
}
}
private class NullParser : IHttpParser
{
private readonly byte[] _startLine = Encoding.ASCII.GetBytes("GET /plaintext HTTP/1.1\r\n");
private readonly byte[] _target = Encoding.ASCII.GetBytes("/plaintext");
private readonly byte[] _hostHeaderName = Encoding.ASCII.GetBytes("Host");
private readonly byte[] _hostHeaderValue = Encoding.ASCII.GetBytes("www.example.com");
private readonly byte[] _acceptHeaderName = Encoding.ASCII.GetBytes("Accept");
private readonly byte[] _acceptHeaderValue = Encoding.ASCII.GetBytes("text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7\r\n\r\n");
private readonly byte[] _connectionHeaderName = Encoding.ASCII.GetBytes("Connection");
private readonly byte[] _connectionHeaderValue = Encoding.ASCII.GetBytes("keep-alive");
public static readonly NullParser Instance = new NullParser();
public bool ParseHeaders(IHttpHeadersHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes)
{
handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
handler.OnHeader(new Span<byte>(_connectionHeaderName), new Span<byte>(_connectionHeaderValue));
consumedBytes = 0;
consumed = buffer.Start;
examined = buffer.End;
return true;
}
public bool ParseRequestLine(IHttpRequestLineHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
{
handler.OnStartLine(HttpMethod.Get,
HttpVersion.Http11,
new Span<byte>(_target),
new Span<byte>(_target),
Span<byte>.Empty,
Span<byte>.Empty,
false);
consumed = buffer.Start;
examined = buffer.End;
return true;
}
public void Reset()
{
}
}
}
}

View File

@ -0,0 +1,57 @@
// 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.Text;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System;
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class NullParser : IHttpParser
{
private readonly byte[] _startLine = Encoding.ASCII.GetBytes("GET /plaintext HTTP/1.1\r\n");
private readonly byte[] _target = Encoding.ASCII.GetBytes("/plaintext");
private readonly byte[] _hostHeaderName = Encoding.ASCII.GetBytes("Host");
private readonly byte[] _hostHeaderValue = Encoding.ASCII.GetBytes("www.example.com");
private readonly byte[] _acceptHeaderName = Encoding.ASCII.GetBytes("Accept");
private readonly byte[] _acceptHeaderValue = Encoding.ASCII.GetBytes("text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7\r\n\r\n");
private readonly byte[] _connectionHeaderName = Encoding.ASCII.GetBytes("Connection");
private readonly byte[] _connectionHeaderValue = Encoding.ASCII.GetBytes("keep-alive");
public static readonly NullParser Instance = new NullParser();
public bool ParseHeaders(IHttpHeadersHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes)
{
handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
handler.OnHeader(new Span<byte>(_connectionHeaderName), new Span<byte>(_connectionHeaderValue));
consumedBytes = 0;
consumed = buffer.Start;
examined = buffer.End;
return true;
}
public bool ParseRequestLine(IHttpRequestLineHandler handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
{
handler.OnStartLine(HttpMethod.Get,
HttpVersion.Http11,
new Span<byte>(_target),
new Span<byte>(_target),
Span<byte>.Empty,
Span<byte>.Empty,
false);
consumed = buffer.Start;
examined = buffer.End;
return true;
}
public void Reset()
{
}
}
}

View File

@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_current{feature.Name} = null;")}
}}
private object FastFeatureGet(Type key)
internal object FastFeatureGet(Type key)
{{{Each(allFeatures, feature => $@"
if (key == {feature.Name}Type)
{{
@ -96,7 +96,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return ExtraFeatureGet(key);
}}
private void FastFeatureSet(Type key, object feature)
internal void FastFeatureSet(Type key, object feature)
{{
_featureRevision++;
{Each(allFeatures, feature => $@"