Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions src/Http/Routing/src/Matching/DfaMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
Expand Down Expand Up @@ -53,7 +53,8 @@ public sealed override Task MatchAsync(HttpContext httpContext, EndpointSelector
// FindCandidateSet will process the DFA and return a candidate set. This does
// some preliminary matching of the URL (mostly the literal segments).
var (candidates, policies) = FindCandidateSet(httpContext, path, segments);
if (candidates.Length == 0)
var candidateCount = candidates.Length;
if (candidateCount == 0)
{
if (log)
{
Expand All @@ -68,6 +69,26 @@ public sealed override Task MatchAsync(HttpContext httpContext, EndpointSelector
Logger.CandidatesFound(_logger, path, candidates);
}

var policyCount = policies.Length;

// This is a fast path for single candidate, 0 policies and default selector
if (policyCount == 0 && candidateCount == 1 && _selector is DefaultEndpointSelector)
Comment thread
davidfowl marked this conversation as resolved.
Outdated
{
ref var candidate = ref candidates[0];
var flags = candidate.Flags;
Comment thread
davidfowl marked this conversation as resolved.
Outdated

// Just strict path matching
if (flags == Candidate.CandidateFlags.None)
{
// TODO: Remove this allocation
context.RouteValues = new RouteValueDictionary();
context.Endpoint = candidate.Endpoint;

// We're done
return Task.CompletedTask;
}
}

// At this point we have a candidate set, defined as a list of endpoints in
// priority order.
//
Expand All @@ -83,7 +104,7 @@ public sealed override Task MatchAsync(HttpContext httpContext, EndpointSelector
// `candidateSet` is the mutable state that we pass to the EndpointSelector.
var candidateSet = new CandidateSet(candidates);

for (var i = 0; i < candidates.Length; i++)
for (var i = 0; i < candidateCount; i++)
{
// PERF: using ref here to avoid copying around big structs.
//
Expand Down Expand Up @@ -165,7 +186,7 @@ public sealed override Task MatchAsync(HttpContext httpContext, EndpointSelector
}
}

if (policies.Length == 0)
if (policyCount == 0)
{
// Perf: avoid a state machine if there are no polices
return _selector.SelectAsync(httpContext, context, candidateSet);
Expand Down