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

Commit c0f88eb

Browse files
benaadamshalter73
authored andcommitted
Faster IFeatureCollection.Get<TFeature> (#2290)
1 parent d996f6b commit c0f88eb

File tree

8 files changed

+715
-219
lines changed

8 files changed

+715
-219
lines changed

benchmarks/Kestrel.Performance/HttpProtocolFeatureCollection.cs

+42-38
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
using System;
55
using System.Buffers;
66
using System.IO.Pipelines;
7+
using System.Runtime.CompilerServices;
8+
using System.Threading;
9+
using System.Threading.Tasks;
710
using BenchmarkDotNet.Attributes;
811
using Microsoft.AspNetCore.Http.Features;
912
using Microsoft.AspNetCore.Server.Kestrel.Core;
@@ -14,65 +17,63 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
1417
{
1518
public class HttpProtocolFeatureCollection
1619
{
17-
private readonly Http1Connection _http1Connection;
18-
private IFeatureCollection _collection;
19-
20-
[Benchmark(Baseline = true)]
21-
public IHttpRequestFeature GetFirstViaFastFeature()
22-
{
23-
return (IHttpRequestFeature)GetFastFeature(typeof(IHttpRequestFeature));
24-
}
25-
26-
[Benchmark]
27-
public IHttpRequestFeature GetFirstViaType()
28-
{
29-
return (IHttpRequestFeature)Get(typeof(IHttpRequestFeature));
30-
}
20+
private readonly IFeatureCollection _collection;
3121

3222
[Benchmark]
33-
public IHttpRequestFeature GetFirstViaExtension()
23+
[MethodImpl(MethodImplOptions.NoInlining)]
24+
public IHttpRequestFeature GetViaTypeOf_First()
3425
{
35-
return _collection.GetType<IHttpRequestFeature>();
26+
return (IHttpRequestFeature)_collection[typeof(IHttpRequestFeature)];
3627
}
3728

3829
[Benchmark]
39-
public IHttpRequestFeature GetFirstViaGeneric()
30+
[MethodImpl(MethodImplOptions.NoInlining)]
31+
public IHttpRequestFeature GetViaGeneric_First()
4032
{
4133
return _collection.Get<IHttpRequestFeature>();
4234
}
4335

4436
[Benchmark]
45-
public IHttpSendFileFeature GetLastViaFastFeature()
37+
[MethodImpl(MethodImplOptions.NoInlining)]
38+
public IHttpSendFileFeature GetViaTypeOf_Last()
4639
{
47-
return (IHttpSendFileFeature)GetFastFeature(typeof(IHttpSendFileFeature));
40+
return (IHttpSendFileFeature)_collection[typeof(IHttpSendFileFeature)];
4841
}
4942

5043
[Benchmark]
51-
public IHttpSendFileFeature GetLastViaType()
44+
[MethodImpl(MethodImplOptions.NoInlining)]
45+
public IHttpSendFileFeature GetViaGeneric_Last()
5246
{
53-
return (IHttpSendFileFeature)Get(typeof(IHttpSendFileFeature));
47+
return _collection.Get<IHttpSendFileFeature>();
5448
}
5549

5650
[Benchmark]
57-
public IHttpSendFileFeature GetLastViaExtension()
51+
[MethodImpl(MethodImplOptions.NoInlining)]
52+
public object GetViaTypeOf_Custom()
5853
{
59-
return _collection.GetType<IHttpSendFileFeature>();
54+
return (IHttpCustomFeature)_collection[typeof(IHttpCustomFeature)];
6055
}
6156

6257
[Benchmark]
63-
public IHttpSendFileFeature GetLastViaGeneric()
58+
[MethodImpl(MethodImplOptions.NoInlining)]
59+
public object GetViaGeneric_Custom()
6460
{
65-
return _collection.Get<IHttpSendFileFeature>();
61+
return _collection.Get<IHttpCustomFeature>();
6662
}
6763

68-
private object Get(Type type)
64+
65+
[Benchmark]
66+
[MethodImpl(MethodImplOptions.NoInlining)]
67+
public object GetViaTypeOf_NotFound()
6968
{
70-
return _collection[type];
69+
return (IHttpNotFoundFeature)_collection[typeof(IHttpNotFoundFeature)];
7170
}
7271

73-
private object GetFastFeature(Type type)
72+
[Benchmark]
73+
[MethodImpl(MethodImplOptions.NoInlining)]
74+
public object GetViaGeneric_NotFound()
7475
{
75-
return _http1Connection.FastFeatureGet(type);
76+
return _collection.Get<IHttpNotFoundFeature>();
7677
}
7778

7879
public HttpProtocolFeatureCollection()
@@ -99,21 +100,24 @@ public HttpProtocolFeatureCollection()
99100

100101
http1Connection.Reset();
101102

102-
_http1Connection = http1Connection;
103+
_collection = http1Connection;
103104
}
104105

105-
[IterationSetup]
106-
public void Setup()
106+
private class SendFileFeature : IHttpSendFileFeature
107107
{
108-
_collection = _http1Connection;
108+
public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellation)
109+
{
110+
throw new NotImplementedException();
111+
}
109112
}
110113

111-
}
112-
public static class IFeatureCollectionExtensions
113-
{
114-
public static T GetType<T>(this IFeatureCollection collection)
114+
private interface IHttpCustomFeature
115+
{
116+
}
117+
118+
private interface IHttpNotFoundFeature
115119
{
116-
return (T)collection[typeof(T)];
117120
}
118121
}
122+
119123
}

src/Kestrel.Core/Internal/Http/Http1Connection.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ private void EnsureHostHeaderExists()
400400

401401
protected override void OnReset()
402402
{
403-
FastFeatureSet(typeof(IHttpUpgradeFeature), this);
403+
ResetIHttpUpgradeFeature();
404404

405405
_requestTimedOut = false;
406406
_requestTargetForm = HttpRequestTarget.Unknown;

src/Kestrel.Core/Internal/Http/HttpProtocol.FeatureCollection.cs

+4-10
Original file line numberDiff line numberDiff line change
@@ -243,20 +243,14 @@ MinDataRate IHttpMinResponseDataRateFeature.MinDataRate
243243
set => MinResponseDataRate = value;
244244
}
245245

246-
object IFeatureCollection.this[Type key]
246+
protected void ResetIHttpUpgradeFeature()
247247
{
248-
get => FastFeatureGet(key) ?? ConnectionFeatures[key];
249-
set => FastFeatureSet(key, value);
248+
_currentIHttpUpgradeFeature = this;
250249
}
251250

252-
TFeature IFeatureCollection.Get<TFeature>()
251+
protected void ResetIHttp2StreamIdFeature()
253252
{
254-
return (TFeature)(FastFeatureGet(typeof(TFeature)) ?? ConnectionFeatures[typeof(TFeature)]);
255-
}
256-
257-
void IFeatureCollection.Set<TFeature>(TFeature instance)
258-
{
259-
FastFeatureSet(typeof(TFeature), instance);
253+
_currentIHttp2StreamIdFeature = this;
260254
}
261255

262256
void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)

0 commit comments

Comments
 (0)