Minor matcher builder allocation optimization (#771)
This commit is contained in:
parent
dbebdbecd6
commit
1c74973c6a
|
|
@ -592,12 +592,23 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
|
|
||||||
// Start with the current node as the root.
|
// Start with the current node as the root.
|
||||||
var work = new List<DfaNode>() { node, };
|
var work = new List<DfaNode>() { node, };
|
||||||
|
List<DfaNode> previousWork = null;
|
||||||
for (var i = 0; i < _nodeBuilders.Length; i++)
|
for (var i = 0; i < _nodeBuilders.Length; i++)
|
||||||
{
|
{
|
||||||
var nodeBuilder = _nodeBuilders[i];
|
var nodeBuilder = _nodeBuilders[i];
|
||||||
|
|
||||||
// Build a list of each
|
// Build a list of each
|
||||||
var nextWork = new List<DfaNode>();
|
List<DfaNode> nextWork;
|
||||||
|
if (previousWork == null)
|
||||||
|
{
|
||||||
|
nextWork = new List<DfaNode>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reuse previous collection for the next collection
|
||||||
|
previousWork.Clear();
|
||||||
|
nextWork = previousWork;
|
||||||
|
}
|
||||||
|
|
||||||
for (var j = 0; j < work.Count; j++)
|
for (var j = 0; j < work.Count; j++)
|
||||||
{
|
{
|
||||||
|
|
@ -639,6 +650,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
parent.Matches?.Clear();
|
parent.Matches?.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousWork = work;
|
||||||
work = nextWork;
|
work = nextWork;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
|
|
||||||
for (var i = 0; i < endpoints.Count; i++)
|
for (var i = 0; i < endpoints.Count; i++)
|
||||||
{
|
{
|
||||||
if (endpoints[i].Metadata.GetMetadata<IHttpMethodMetadata>()?.HttpMethods.Any() == true)
|
if (endpoints[i].Metadata.GetMetadata<IHttpMethodMetadata>()?.HttpMethods.Count > 0)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -219,31 +219,41 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public PolicyJumpTable BuildJumpTable(int exitDestination, IReadOnlyList<PolicyJumpTableEdge> edges)
|
public PolicyJumpTable BuildJumpTable(int exitDestination, IReadOnlyList<PolicyJumpTableEdge> edges)
|
||||||
{
|
{
|
||||||
var destinations = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, int> destinations = null;
|
||||||
var corsPreflightDestinations = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, int> corsPreflightDestinations = null;
|
||||||
for (var i = 0; i < edges.Count; i++)
|
for (var i = 0; i < edges.Count; i++)
|
||||||
{
|
{
|
||||||
// We create this data, so it's safe to cast it.
|
// We create this data, so it's safe to cast it.
|
||||||
var key = (EdgeKey)edges[i].State;
|
var key = (EdgeKey)edges[i].State;
|
||||||
if (key.IsCorsPreflightRequest)
|
if (key.IsCorsPreflightRequest)
|
||||||
{
|
{
|
||||||
|
if (corsPreflightDestinations == null)
|
||||||
|
{
|
||||||
|
corsPreflightDestinations = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
corsPreflightDestinations.Add(key.HttpMethod, edges[i].Destination);
|
corsPreflightDestinations.Add(key.HttpMethod, edges[i].Destination);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (destinations == null)
|
||||||
|
{
|
||||||
|
destinations = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
destinations.Add(key.HttpMethod, edges[i].Destination);
|
destinations.Add(key.HttpMethod, edges[i].Destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int corsPreflightExitDestination = exitDestination;
|
int corsPreflightExitDestination = exitDestination;
|
||||||
if (corsPreflightDestinations.TryGetValue(AnyMethod, out var matchesAnyVerb))
|
if (corsPreflightDestinations != null && corsPreflightDestinations.TryGetValue(AnyMethod, out var matchesAnyVerb))
|
||||||
{
|
{
|
||||||
// If we have endpoints that match any HTTP method, use that as the exit.
|
// If we have endpoints that match any HTTP method, use that as the exit.
|
||||||
corsPreflightExitDestination = matchesAnyVerb;
|
corsPreflightExitDestination = matchesAnyVerb;
|
||||||
corsPreflightDestinations.Remove(AnyMethod);
|
corsPreflightDestinations.Remove(AnyMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destinations.TryGetValue(AnyMethod, out matchesAnyVerb))
|
if (destinations != null && destinations.TryGetValue(AnyMethod, out matchesAnyVerb))
|
||||||
{
|
{
|
||||||
// If we have endpoints that match any HTTP method, use that as the exit.
|
// If we have endpoints that match any HTTP method, use that as the exit.
|
||||||
exitDestination = matchesAnyVerb;
|
exitDestination = matchesAnyVerb;
|
||||||
|
|
@ -304,7 +314,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
_corsPreflightExitDestination = corsPreflightExitDestination;
|
_corsPreflightExitDestination = corsPreflightExitDestination;
|
||||||
_corsPreflightDestinations = corsPreflightDestinations;
|
_corsPreflightDestinations = corsPreflightDestinations;
|
||||||
|
|
||||||
_supportsCorsPreflight = _corsPreflightDestinations.Count > 0;
|
_supportsCorsPreflight = _corsPreflightDestinations != null && _corsPreflightDestinations.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetDestination(HttpContext httpContext)
|
public override int GetDestination(HttpContext httpContext)
|
||||||
|
|
@ -318,12 +328,14 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
httpContext.Request.Headers.TryGetValue(AccessControlRequestMethod, out var accessControlRequestMethod) &&
|
httpContext.Request.Headers.TryGetValue(AccessControlRequestMethod, out var accessControlRequestMethod) &&
|
||||||
!StringValues.IsNullOrEmpty(accessControlRequestMethod))
|
!StringValues.IsNullOrEmpty(accessControlRequestMethod))
|
||||||
{
|
{
|
||||||
return _corsPreflightDestinations.TryGetValue(accessControlRequestMethod, out destination)
|
return _corsPreflightDestinations != null &&
|
||||||
|
_corsPreflightDestinations.TryGetValue(accessControlRequestMethod, out destination)
|
||||||
? destination
|
? destination
|
||||||
: _corsPreflightExitDestination;
|
: _corsPreflightExitDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _destinations.TryGetValue(httpMethod, out destination) ? destination : _exitDestination;
|
return _destinations != null &&
|
||||||
|
_destinations.TryGetValue(httpMethod, out destination) ? destination : _exitDestination;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue