Perf improvements for EndpointSelector
This commit is contained in:
parent
ed15bad5fb
commit
a2f404f4d5
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
internal class DefaultEndpointSelector : EndpointSelector
|
internal class DefaultEndpointSelector : EndpointSelector
|
||||||
{
|
{
|
||||||
private readonly IEndpointSelectorPolicy[] _selectorPolicies;
|
private readonly IEndpointSelectorPolicy[] _selectorPolicies;
|
||||||
|
|
||||||
public DefaultEndpointSelector(IEnumerable<MatcherPolicy> matcherPolicies)
|
public DefaultEndpointSelector(IEnumerable<MatcherPolicy> matcherPolicies)
|
||||||
{
|
{
|
||||||
if (matcherPolicies == null)
|
if (matcherPolicies == null)
|
||||||
|
|
@ -23,13 +23,73 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
_selectorPolicies = matcherPolicies.OrderBy(p => p.Order).OfType<IEndpointSelectorPolicy>().ToArray();
|
_selectorPolicies = matcherPolicies.OrderBy(p => p.Order).OfType<IEndpointSelectorPolicy>().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task SelectAsync(
|
public override Task SelectAsync(
|
||||||
|
HttpContext httpContext,
|
||||||
|
EndpointSelectorContext context,
|
||||||
|
CandidateSet candidateSet)
|
||||||
|
{
|
||||||
|
if (httpContext == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(httpContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidateSet == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(candidateSet));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_selectorPolicies.Length > 0)
|
||||||
|
{
|
||||||
|
// Slow path: we need async to run policies
|
||||||
|
return SelectAsyncSlow(httpContext, context, candidateSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast path: We can specialize for trivial numbers of candidates since there can
|
||||||
|
// be no ambiguities and we don't need to run policies.
|
||||||
|
switch (candidateSet.Count)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if (candidateSet.IsValidCandidate(0))
|
||||||
|
{
|
||||||
|
ref var state = ref candidateSet[0];
|
||||||
|
context.Endpoint = state.Endpoint;
|
||||||
|
context.RouteValues = state.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Slow path: There's more than one candidate (to say nothing of validity) so we
|
||||||
|
// have to process for ambiguities.
|
||||||
|
ProcessFinalCandidates(httpContext, context, candidateSet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SelectAsyncSlow(
|
||||||
HttpContext httpContext,
|
HttpContext httpContext,
|
||||||
EndpointSelectorContext context,
|
EndpointSelectorContext context,
|
||||||
CandidateSet candidateSet)
|
CandidateSet candidateSet)
|
||||||
{
|
{
|
||||||
var selectorPolicies = _selectorPolicies;
|
var selectorPolicies = _selectorPolicies;
|
||||||
for (var i = 0; i < _selectorPolicies.Length; i++)
|
for (var i = 0; i < selectorPolicies.Length; i++)
|
||||||
{
|
{
|
||||||
await selectorPolicies[i].ApplyAsync(httpContext, context, candidateSet);
|
await selectorPolicies[i].ApplyAsync(httpContext, context, candidateSet);
|
||||||
if (context.Endpoint != null)
|
if (context.Endpoint != null)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue