Remove bitfield for locally implemented interface items

Only generate type statics for cached features
This commit is contained in:
Ben Adams 2015-10-08 00:05:27 -04:00 committed by Louis DeJardin
parent 3c20053d9a
commit 8f41e47eca
2 changed files with 61 additions and 117 deletions

View File

@ -6,23 +6,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{
public partial class Frame
{
private const long flagIHttpRequestFeature = 1;
private const long flagIHttpResponseFeature = 2;
private const long flagIHttpRequestIdentifierFeature = 4;
private const long flagIHttpSendFileFeature = 8;
private const long flagIServiceProvidersFeature = 16;
private const long flagIHttpAuthenticationFeature = 32;
private const long flagIHttpRequestLifetimeFeature = 64;
private const long flagIQueryFeature = 128;
private const long flagIFormFeature = 256;
private const long flagIResponseCookiesFeature = 512;
private const long flagIItemsFeature = 1024;
private const long flagIHttpConnectionFeature = 2048;
private const long flagITlsConnectionFeature = 4096;
private const long flagIHttpUpgradeFeature = 8192;
private const long flagIHttpWebSocketFeature = 16384;
private const long flagISessionFeature = 32768;
private static readonly Type IHttpRequestFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature);
private static readonly Type IHttpResponseFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature);
private static readonly Type IHttpRequestIdentifierFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature);
@ -40,7 +23,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
private static readonly Type IHttpWebSocketFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature);
private static readonly Type ISessionFeatureType = typeof(global::Microsoft.AspNet.Http.Features.ISessionFeature);
private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature);
private static readonly Type IHttpUpgradeFeatureType = typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature);
private object _currentIHttpRequestFeature;
private object _currentIHttpResponseFeature;
private object _currentIHttpRequestIdentifierFeature;
private object _currentIServiceProvidersFeature;
private object _currentIHttpRequestLifetimeFeature;
@ -48,41 +34,35 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
private object _currentIHttpAuthenticationFeature;
private object _currentIQueryFeature;
private object _currentIFormFeature;
private long _featureOverridenFlags = 0L;
private object _currentIHttpUpgradeFeature;
private void FastReset()
{
_featureOverridenFlags = 0L;
_currentIHttpRequestFeature = this;
_currentIHttpResponseFeature = this;
_currentIHttpUpgradeFeature = this;
_currentIHttpRequestIdentifierFeature = null;
_currentIServiceProvidersFeature = null;
_currentIHttpRequestLifetimeFeature = null;
_currentIHttpConnectionFeature = null;
_currentIHttpAuthenticationFeature = null;
_currentIQueryFeature = null;
_currentIFormFeature = null;
}
private object FastFeatureGet(Type key)
{
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature))
{
if ((_featureOverridenFlags & flagIHttpRequestFeature) == 0L)
{
return this;
}
return SlowFeatureGet(key);
return _currentIHttpRequestFeature;
}
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature))
{
if ((_featureOverridenFlags & flagIHttpResponseFeature) == 0L)
{
return this;
}
return SlowFeatureGet(key);
return _currentIHttpResponseFeature;
}
if (key == IHttpRequestIdentifierFeatureType)
{
if ((_featureOverridenFlags & flagIHttpRequestIdentifierFeature) == 0L)
{
return this;
}
return SlowFeatureGet(key);
}
if (key == IHttpSendFileFeatureType)
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature))
{
if ((_featureOverridenFlags & flagIHttpSendFileFeature) == 0L)
{
@ -146,7 +126,16 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
}
return SlowFeatureGet(key);
}
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature))
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature))
{
return _currentIHttpUpgradeFeature;
}
return SlowFeatureGet(key);
}
private object SlowFeatureGet(Type key)
{
if (MaybeExtra == null)
{
if ((_featureOverridenFlags & flagIHttpConnectionFeature) == 0L)
{
@ -189,53 +178,20 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
return SlowFeatureGet(key);
}
private object SlowFeatureGet(Type key)
{
object feature = null;
if (MaybeExtra?.TryGetValue(key, out feature) ?? false)
{
return feature;
}
return null;
}
private void FastFeatureSetInner(long flag, Type key, object feature)
{
Extra[key] = feature;
// Altering only an individual bit of the long
// so need to make sure other concurrent bit changes are not overridden
// in an atomic yet lock-free manner
long currentFeatureFlags;
long updatedFeatureFlags;
do
{
currentFeatureFlags = _featureOverridenFlags;
updatedFeatureFlags = currentFeatureFlags | flag;
} while (System.Threading.Interlocked.CompareExchange(ref _featureOverridenFlags, updatedFeatureFlags, currentFeatureFlags) != currentFeatureFlags);
System.Threading.Interlocked.Increment(ref _featureRevision);
}
private void FastFeatureSet(Type key, object feature)
{
if (key == IHttpRequestFeatureType)
{
FastFeatureSetInner(flagIHttpRequestFeature, key, feature);
_currentIHttpRequestFeature = feature;
return;
}
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature))
{
FastFeatureSetInner(flagIHttpResponseFeature, key, feature);
_currentIHttpResponseFeature = feature;
return;
}
if (key == IHttpRequestIdentifierFeatureType)
{
FastFeatureSetInner(flagIHttpRequestIdentifierFeature, key, feature);
return;
}
if (key == IHttpSendFileFeatureType)
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature))
{
FastFeatureSetInner(flagIHttpSendFileFeature, key, feature);
return;
@ -300,24 +256,25 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
FastFeatureSetInner(flagISessionFeature, key, feature);
return;
}
Extra[key] = feature;
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature))
{
_currentIHttpUpgradeFeature = feature;
return;
};
SetExtra(key, feature);
}
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
{
if ((_featureOverridenFlags & flagIHttpRequestFeature) == 0L)
if (_currentIHttpRequestFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpRequestFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpRequestFeature);
yield return new KeyValuePair<Type, object>(IHttpRequestFeatureType, _currentIHttpRequestFeature as global::Microsoft.AspNet.Http.Features.IHttpRequestFeature);
}
if ((_featureOverridenFlags & flagIHttpResponseFeature) == 0L)
if (_currentIHttpResponseFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpResponseFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpResponseFeature);
yield return new KeyValuePair<Type, object>(IHttpResponseFeatureType, _currentIHttpResponseFeature as global::Microsoft.AspNet.Http.Features.IHttpResponseFeature);
}
if ((_featureOverridenFlags & flagIHttpRequestIdentifierFeature) == 0L)
{
yield return new KeyValuePair<Type, object>(IHttpRequestIdentifierFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature);
}
if ((_featureOverridenFlags & flagIHttpSendFileFeature) == 0L)
if (_currentIHttpRequestIdentifierFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpSendFileFeatureType, this as global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature);
}
@ -369,6 +326,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{
yield return new KeyValuePair<Type, object>(ISessionFeatureType, this as global::Microsoft.AspNet.Http.Features.ISessionFeature);
}
if (_currentIHttpUpgradeFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpUpgradeFeatureType, _currentIHttpUpgradeFeature as global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature);
}
if (MaybeExtra != null)
{
foreach(var item in MaybeExtra)

View File

@ -54,6 +54,10 @@ namespace Microsoft.AspNet.Server.Kestrel.GeneratedCode
typeof(IHttpUpgradeFeature),
};
// Only the always, common and implmented features will have backed objects
// the sometimes, rare and user-defined features will use the MaybeExtra collection
var cachedFeatures = alwaysFeatures.Concat(commonFeatures).Union(implementedFeatures);
return $@"
using System;
using System.Collections.Generic;
@ -61,31 +65,18 @@ using System.Collections.Generic;
namespace Microsoft.AspNet.Server.Kestrel.Http
{{
public partial class Frame
{{
{Each(commonFeatures.Select((feature, index) => new { feature, index }), entry => $@"
private const long flag{entry.feature.Name} = {1 << entry.index};")}
{Each(commonFeatures, feature => $@"
{{{Each(cachedFeatures, feature => $@"
private static readonly Type {feature.Name}Type = typeof(global::{feature.FullName});")}
private long _featureOverridenFlags = 0L;
private void FastReset()
{{
_featureOverridenFlags = 0L;
{{{Each(implementedFeatures, feature => $@"
_current{feature.Name} = this;")}
{Each(cachedFeatures.Where( f => !implementedFeatures.Contains(f)), feature => $@"
_current{feature.Name} = null;")}
}}
private object FastFeatureGet(Type key)
{{{Each(commonFeatures, feature => $@"
if (key == {feature.Name}Type)
{{
if ((_featureOverridenFlags & flag{feature.Name}) == 0L)
{{
return this;
}}
return SlowFeatureGet(key);
}}")}
{Each(cachedFeatures, feature => $@"
{{{Each(cachedFeatures, feature => $@"
if (key == typeof(global::{feature.FullName}))
{{
return _current{feature.Name};
@ -119,18 +110,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
updatedFeatureFlags = currentFeatureFlags | flag;
}} while (System.Threading.Interlocked.CompareExchange(ref _featureOverridenFlags, updatedFeatureFlags, currentFeatureFlags) != currentFeatureFlags);
System.Threading.Interlocked.Increment(ref _featureRevision);
}}
private void FastFeatureSet(Type key, object feature)
{{
_featureRevision++;
{Each(implementedFeatures, feature => $@"
if (key == typeof(global::{feature.FullName}))
{{
FastFeatureSetInner(flag{feature.Name}, key, feature);
return;
}}")};
{Each(cachedFeatures, feature => $@"
if (key == typeof(global::{feature.FullName}))
{{
@ -141,10 +123,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
}}
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
{{{Each(commonFeatures, feature => $@"
if ((_featureOverridenFlags & flag{feature.Name}) == 0L)
{{{Each(cachedFeatures, feature => $@"
if (_current{feature.Name} != null)
{{
yield return new KeyValuePair<Type, object>({feature.Name}Type, this as global::{feature.FullName});
yield return new KeyValuePair<Type, object>({feature.Name}Type, _current{feature.Name} as global::{feature.FullName});
}}")}
if (MaybeExtra != null)
{{