Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 54 additions & 40 deletions benchmarks/Kestrel.Performance/HttpProtocolFeatureCollection.cs
Original file line number Diff line number Diff line change
@@ -1,8 +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;
using System.IO.Pipelines;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
Expand All @@ -14,69 +16,70 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
[Config(typeof(CoreConfig))]
public class HttpProtocolFeatureCollection
{
private readonly Http1Connection<object> _http1Connection;
private IFeatureCollection _collection;

[Benchmark(Baseline = true)]
public IHttpRequestFeature GetFirstViaFastFeature()
{
return (IHttpRequestFeature)GetFastFeature(typeof(IHttpRequestFeature));
}
private readonly IFeatureCollection _collection;

[Benchmark]
public IHttpRequestFeature GetFirstViaType()
[MethodImpl(MethodImplOptions.NoInlining)]
public IHttpRequestFeature GetViaTypeOf_First()
{
return (IHttpRequestFeature)Get(typeof(IHttpRequestFeature));
return (IHttpRequestFeature)_collection[typeof(IHttpRequestFeature)];
}

[Benchmark]
public IHttpRequestFeature GetFirstViaExtension()
{
return _collection.GetType<IHttpRequestFeature>();
}

[Benchmark]
public IHttpRequestFeature GetFirstViaGeneric()
[MethodImpl(MethodImplOptions.NoInlining)]
public IHttpRequestFeature GetViaGeneric_First()
{
return _collection.Get<IHttpRequestFeature>();
}

[Benchmark]
public IHttpSendFileFeature GetLastViaFastFeature()
[MethodImpl(MethodImplOptions.NoInlining)]
public IHttpSendFileFeature GetViaTypeOf_Last()
{
return (IHttpSendFileFeature)GetFastFeature(typeof(IHttpSendFileFeature));
return (IHttpSendFileFeature)_collection[typeof(IHttpSendFileFeature)];
}

[Benchmark]
public IHttpSendFileFeature GetLastViaType()
[MethodImpl(MethodImplOptions.NoInlining)]
public IHttpSendFileFeature GetViaGeneric_Last()
{
return (IHttpSendFileFeature)Get(typeof(IHttpSendFileFeature));
return _collection.Get<IHttpSendFileFeature>();
}

[Benchmark]
public IHttpSendFileFeature GetLastViaExtension()
[MethodImpl(MethodImplOptions.NoInlining)]
public object GetViaTypeOf_Custom()
{
return _collection.GetType<IHttpSendFileFeature>();
return (IHttpCustomFeature)_collection[typeof(IHttpCustomFeature)];
}

[Benchmark]
public IHttpSendFileFeature GetLastViaGeneric()
[MethodImpl(MethodImplOptions.NoInlining)]
public object GetViaGeneric_Custom()
{
return _collection.Get<IHttpSendFileFeature>();
return _collection.Get<IHttpCustomFeature>();
}

private object Get(Type type)

[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public object GetViaTypeOf_NotFound()
{
return _collection[type];
return (IHttpNotFoundFeature)_collection[typeof(IHttpNotFoundFeature)];
}

private object GetFastFeature(Type type)
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public object GetViaGeneric_NotFound()
{
return _http1Connection.FastFeatureGet(type);
return _collection.Get<IHttpNotFoundFeature>();
}

public HttpProtocolFeatureCollection()
{
var pipeFactory = new PipeFactory();
var pair = pipeFactory.CreateConnectionPair();

var serviceContext = new ServiceContext
{
HttpParserFactory = _ => NullParser<Http1ParsingHandler>.Instance,
Expand All @@ -86,24 +89,35 @@ public HttpProtocolFeatureCollection()
{
ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(),
PipeFactory = new PipeFactory()
PipeFactory = pipeFactory,
Application = pair.Application,
Transport = pair.Transport
};

_http1Connection = new Http1Connection<object>(application: null, context: http1ConnectionContext);
var http1Connection = new Http1Connection<object>(application: null, context: http1ConnectionContext);
http1Connection.Reset();

_collection = http1Connection;

IHttpSendFileFeature sendFileFeature = new SendFileFeature();
_collection.Set(sendFileFeature);
}

[IterationSetup]
public void Setup()

private class SendFileFeature : IHttpSendFileFeature
{
_collection = _http1Connection;
public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellation)
{
throw new System.NotImplementedException();
}
}

}
public static class IFeatureCollectionExtensions
{
public static T GetType<T>(this IFeatureCollection collection)
private interface IHttpCustomFeature
{
}

private interface IHttpNotFoundFeature
{
return (T)collection[typeof(T)];
}
}
}
2 changes: 1 addition & 1 deletion src/Kestrel.Core/Internal/Http/Http1Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ protected void EnsureHostHeaderExists()

protected override void OnReset()
{
FastFeatureSet(typeof(IHttpUpgradeFeature), this);
ResetIHttpUpgradeFeature();

_requestTimedOut = false;
_requestTargetForm = HttpRequestTarget.Unknown;
Expand Down
15 changes: 4 additions & 11 deletions src/Kestrel.Core/Internal/Http/HttpProtocol.FeatureCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
using Microsoft.Extensions.Primitives;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
Expand Down Expand Up @@ -244,20 +243,14 @@ MinDataRate IHttpMinResponseDataRateFeature.MinDataRate
set => MinResponseDataRate = value;
}

object IFeatureCollection.this[Type key]
protected void ResetIHttpUpgradeFeature()
{
get => FastFeatureGet(key) ?? ConnectionFeatures[key];
set => FastFeatureSet(key, value);
_currentIHttpUpgradeFeature = this;
}

TFeature IFeatureCollection.Get<TFeature>()
protected void ResetIHttp2StreamIdFeature()
{
return (TFeature)(FastFeatureGet(typeof(TFeature)) ?? ConnectionFeatures[typeof(TFeature)]);
}

void IFeatureCollection.Set<TFeature>(TFeature instance)
{
FastFeatureSet(typeof(TFeature), instance);
_currentIHttp2StreamIdFeature = this;
}

void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)
Expand Down
Loading