Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Commit

Permalink
Faster IFeatureCollection.Get<TFeature>
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams committed Feb 11, 2018
1 parent f65e892 commit 2d17398
Show file tree
Hide file tree
Showing 8 changed files with 715 additions and 220 deletions.
80 changes: 42 additions & 38 deletions benchmarks/Kestrel.Performance/HttpProtocolFeatureCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
using System;
using System.Buffers;
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,65 +17,63 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class HttpProtocolFeatureCollection
{
private readonly Http1Connection _http1Connection;
private IFeatureCollection _collection;

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

[Benchmark]
public IHttpRequestFeature GetFirstViaType()
{
return (IHttpRequestFeature)Get(typeof(IHttpRequestFeature));
}
private readonly IFeatureCollection _collection;

[Benchmark]
public IHttpRequestFeature GetFirstViaExtension()
[MethodImpl(MethodImplOptions.NoInlining)]
public IHttpRequestFeature GetViaTypeOf_First()
{
return _collection.GetType<IHttpRequestFeature>();
return (IHttpRequestFeature)_collection[typeof(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()
Expand All @@ -99,21 +100,24 @@ public HttpProtocolFeatureCollection()

http1Connection.Reset();

_http1Connection = http1Connection;
_collection = http1Connection;
}

[IterationSetup]
public void Setup()
private class SendFileFeature : IHttpSendFileFeature
{
_collection = _http1Connection;
public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellation)
{
throw new 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 @@ -401,7 +401,7 @@ private 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 @@ -243,21 +243,14 @@ MinDataRate IHttpMinResponseDataRateFeature.MinDataRate
get => MinResponseDataRate;
set => MinResponseDataRate = value;
}

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

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

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

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

0 comments on commit 2d17398

Please sign in to comment.