Skip to content

Reduce allocations in HttpMethodMatcherPolicy.GetEdges - #70154

Open
davidfowl wants to merge 4 commits into
mainfrom
perf/httpmethod-edges
Open

davidfowl wants to merge 4 commits into
mainfrom
perf/httpmethod-edges

Conversation

@davidfowl

@davidfowl davidfowl commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Reduce allocations in HttpMethodMatcherPolicy.GetEdges

Reduce allocations and time in HttpMethodMatcherPolicy.GetEdges during DFA build

Description

  • GetEdges runs for many nodes while the DFA is built. It collected a handful of edges in a Dictionary<EdgeKey, List<Endpoint>>, and most of its time went to growing that dictionary.
  • It now uses an insertion-ordered list with a linear search and the same key equality, so the edge order is unchanged. EdgeKey.Equals is case-insensitive but GetHashCode is ordinal. The dictionary therefore kept custom methods that differ only by case (for example MERGE and merge) as separate edges. The lookup keeps exactly that rule: an ordinal fast path, otherwise Equals plus a hash-code match.
  • It reuses a static array for the any-method (*) sentinel.
  • The lookup uses only safe code (a plain List<T> indexer loop), with no CollectionsMarshal, Unsafe or custom vectorization.
  • Adds a GetEdges benchmark to HttpMethodMatcherPolicyBenchmark.
  • Adds GetEdges_CustomMethodsDifferingInCase_CreateSeparateEdgesInInsertionOrder, which pins the existing edge order and case handling. It passes on both main and this branch.

There are no public API or behavior changes.

Benchmarks

Release builds of Microsoft.AspNetCore.Routing.Microbenchmarks using main's source and this branch's source with the same benchmark harness. Settings: in-process toolchain, 5 warmup and 15 measured iterations, MemoryDiagnoser, 3 interleaved before/after rounds, Linux VM, .NET 12 alpha. Values are the mean of the 3 rounds.

Benchmark Before After Alloc before Alloc after
HttpMethodMatcherPolicyBenchmark.GetEdges (DestinationCount=3) 628 ns 351 ns 1,288 B 864 B
HttpMethodMatcherPolicyBenchmark.GetEdges (DestinationCount=5) 839 ns 557 ns 1,560 B 1,352 B
HttpMethodMatcherPolicyBenchmark.GetEdges (DestinationCount=11) 1,801 ns 1,456 ns 3,280 B 2,816 B
MatcherBuilderGithubBenchmark.Dfa 601 µs 570 µs 672,945 B 644,182 B

Each round showed the same direction for GetEdges. The full GitHub-routes DFA build allocates 4.3% less; its time was lower in every round, but the difference is close to run-to-run noise.

Tests

  • Microsoft.AspNetCore.Routing.Tests: 3506/3506 passed, including the new test.

🤖 Posted by ASP.NET Core Perf 2 (AI Agent)

davidfowl and others added 3 commits October 31, 2026 00:30
GetEdges is called for many nodes while building the DFA. It used a
Dictionary<EdgeKey, List<Endpoint>> to collect a handful of edges, and
most of its time went into growing that dictionary. Use an
insertion-ordered list with a linear search instead (keys are compared
ordinally, like the dictionary's hash code), and reuse a static array
for the 'any method' sentinel.

Adds a GetEdges benchmark to HttpMethodMatcherPolicyBenchmark.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@davidfowl
davidfowl requested a review from halter73 as a code owner October 31, 2026 00:47
Copilot AI balanced review requested due to automatic review settings October 31, 2026 00:47
@github-actions github-actions Bot added the area-routing Includes: endpoint routing and URL matching label Oct 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are reported for the routing edge-allocation optimization.

No open issues 🎉

What changed in this PR

Reduces allocations in HttpMethodMatcherPolicy.GetEdges during routing DFA construction while preserving existing edge ordering and key-matching behavior.

Changes:

  • Replaces dictionary-based edge collection with an insertion-ordered list and linear lookup.
  • Reuses a static array for the any-method sentinel.
  • Adds a focused benchmark and a regression test for custom HTTP methods differing only by case.
File Description
src/​Http/​Routing/​test/​UnitTests/​Matching/​HttpMethodMatcherPolicyTest.cs Tests separate edges and insertion order for case-differing custom methods.
src/​Http/​Routing/​src/​Matching/​HttpMethodMatcherPolicy.cs Uses list-based edge lookup and reuses the any-method array.
src/​Http/​Routing/​perf/​Microbenchmarks/​Matching/​HttpMethodMatcherPolicyBenchmark.cs Adds a GetEdges benchmark with method-specific, CORS, and unrestricted endpoints.

Review effort: Balanced

Copy link
Copy Markdown
Member Author

/azp run aspnetcore-components-e2e

Rerunning: the only failure is ServerRoutingTest.NavigationLock_CanBlockNavigation_ThenCancel, which Build Analysis shows with a ~1.6% failure rate. It covers Blazor client-side navigation locking, not endpoint HTTP-method matching.

🤖 Posted by ASP.NET Core Perf 2 (AI Agent)

@azure-pipelines

Copy link
Copy Markdown
No pipelines are associated with this pull request.

Copy link
Copy Markdown
Member Author

CI status: aspnetcore-ci (builds, Helix and platform tests) is green. The only remaining failure is aspnetcore-components-e2e (Mono server) on ServerRoutingTest.NavigationLock_CanBlockExternalNavigation. Build Analysis lists a ~25.6% failure rate for that test, and it doesn't depend on endpoint HTTP-method matching. The earlier runs each failed on a different Blazor UI test, and this pipeline also failed on 4 of the last 5 main commits. Routing tests pass.

🤖 Posted by ASP.NET Core Perf 2 (AI Agent)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen

PureWeen commented Nov 1, 2026

Copy link
Copy Markdown
Member

/review

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-routing Includes: endpoint routing and URL matching

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants