Skip to content

Fix CsrfProtectionMiddleware perf degradations - #67488

Merged
DeagleGross merged 6 commits into
dotnet:mainfrom
DeagleGross:deaglegross-dmkorolev-csrf-perf-no-items
Jul 2, 2026
Merged

Fix CsrfProtectionMiddleware perf degradations#67488
DeagleGross merged 6 commits into
dotnet:mainfrom
DeagleGross:deaglegross-dmkorolev-csrf-perf-no-items

Conversation

@DeagleGross

@DeagleGross DeagleGross commented Jun 30, 2026

Copy link
Copy Markdown
Member

Fixes degradation noticed by @BrennanConroy (thanks!) #67119 (comment)

There are several problems:

  1. CsrfProtectionMiddleware was unconditionally writing MiddlewareInvokedKeys.CsrfProtection to context.Items. The hot-path where writing to context.Items is useless is when endpoint is not null, but there is no antiforgeryMetadata. In such case CSRF just skips since endpoint is intentionally not wired with Antiforgery validation mechanisms.
  2. Same idea - CsrfProtectionMiddleware is useless without Routing (because there is no context.GetEndpoint() and obviosly antiforgery metadata. However, we were always registering CsrfProtectionMiddleware in the pipeline, when Routing was injected only if _builtApplication.DataSources.Count > 0 is true. So I applied same check there.

Testing

For current main code:

Metric Value
Max Allocation Rate (B/sec) 2,378,236,488
Requests/sec 8,756,812

and for updated code:

Metric Value Delta
Max Allocation Rate (B/sec) 4,971,768 −99.79%
Requests/sec 10,791,848 +23.2%

DeagleGross and others added 3 commits June 30, 2026 14:08
PR dotnet#67119 introduced an unconditional
context.Items[MiddlewareInvokedKeys.CsrfProtection] = ...
write in CsrfProtectionMiddleware.InvokeAsync, which forces the lazy
HttpContext.Items dictionary to allocate on every request. This blew up
allocations on hot non-antiforgery paths (~264 B/request extra; ~1.3 GB/s
at TechEmpower plaintext throughput). See PR dotnet#67119 comment 4835979504.

Gate the marker write on either endpoint == null (re-execute into an
antiforgery-required page must still find the marker) or the matched
endpoint carrying any IAntiforgeryMetadata (both DisableAntiforgery()
for re-execute and the FormFeature backstop for RequiresValidation:true).
For endpoints with no antiforgery metadata at all - the hot non-antiforgery
path - the marker has no consumer and is now skipped.

Adds CsrfProtection_HotPath_NoEndpointMetadata_DoesNotAllocateItemsDictionary
as a regression guard using GC.GetAllocatedBytesForCurrentThread().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@DeagleGross DeagleGross self-assigned this Jun 30, 2026
Copilot AI review requested due to automatic review settings June 30, 2026 12:43
@DeagleGross
DeagleGross requested a review from halter73 as a code owner June 30, 2026 12:43
@DeagleGross DeagleGross added area-perf Performance infrastructure issues feature-antiforgery labels Jun 30, 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.

Pull request overview

Optimizes the auto-injected CsrfProtectionMiddleware hot path by avoiding unnecessary HttpContext.Items initialization when an endpoint has no antiforgery metadata, while preserving the marker behavior needed for reroute/re-execute scenarios and antiforgery/disable-antiforgery endpoints.

Changes:

  • Conditionally stamps the MiddlewareInvokedKeys.CsrfProtection marker only when endpoint is null or when IAntiforgeryMetadata is present.
  • Updates integration tests to assert the marker is not set for endpoints without antiforgery metadata.
Show a summary per file
File Description
src/DefaultBuilder/src/Internal/CsrfProtectionMiddleware.cs Avoids HttpContext.Items allocation by not stamping the marker on the no-antiforgery-metadata path.
src/DefaultBuilder/test/Microsoft.AspNetCore.Tests/CsrfProtectionIntegrationTests.cs Adjusts assertions to reflect that the marker is not set when the endpoint has no antiforgery metadata.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 1

Comment thread src/DefaultBuilder/src/Internal/CsrfProtectionMiddleware.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@DeagleGross
DeagleGross force-pushed the deaglegross-dmkorolev-csrf-perf-no-items branch from ec17a1d to 556d8f9 Compare July 1, 2026 11:59
@DeagleGross DeagleGross changed the title Skip HttpContext.Items allocation in CsrfProtectionMiddleware hot path Fix CsrfProtectionMiddleware perf degradations Jul 1, 2026
Comment thread src/DefaultBuilder/src/Internal/CsrfProtectionMiddleware.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-perf Performance infrastructure issues feature-antiforgery

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants