Skip to content

Perf regression: antiforgery-generation, antiforgery-validation #66536

Description

@pr-benchmarks
Scenario Environment Date Old RPS New RPS Change Deviation StDev Dependencies
antiforgery-generation Antiforgery Token Generation 8- Trends Intel Lin 04/29/2026 02:21:01 234,222 215,403 -8.03 % (-18,819) 👎 -5.79 σ 3,248.51
Changes
NameVersionDiff
Microsoft.AspNetCore.Antiforgery.dll 11.0.0-preview.4.26215.118 -> 11.0.0-preview.5.26228.102 dotnet/dotnet@37d611a...d3d9bbb
Antiforgery.dll 1.0.0 -> 1.0.0 aspnet/Benchmarks@3c382ed...a494b8d
Microsoft.AspNetCore.App 11.0.0-preview.4.26215.118 -> 11.0.0-preview.5.26228.102 37d611a...d3d9bbb
Microsoft.NETCore.App 11.0.0-preview.4.26215.118 -> 11.0.0-preview.5.26228.102 dotnet/runtime@37d611a...d3d9bbb
antiforgery-validation Antiforgery Token Validation 8- Trends Intel Lin 04/29/2026 02:20:12 259,820 230,786 -11.17 % (-29,034) 👎 -9.01 σ 3,223.61
Changes
NameVersionDiff
Microsoft.AspNetCore.Antiforgery.dll 11.0.0-preview.4.26215.118 -> 11.0.0-preview.5.26228.102 dotnet/dotnet@37d611a...d3d9bbb
Antiforgery.dll 1.0.0 -> 1.0.0 aspnet/Benchmarks@3c382ed...a494b8d
Microsoft.AspNetCore.App 11.0.0-preview.4.26215.118 -> 11.0.0-preview.5.26228.102 37d611a...d3d9bbb
Microsoft.NETCore.App 11.0.0-preview.4.26215.118 -> 11.0.0-preview.5.26228.102 dotnet/runtime@37d611a...d3d9bbb

PowerBI Dashboard

@sebastienros

Activity

  1. sebastienros commented on Apr 30, 2026

    @sebastienros
    Member
  2. added this to the 11.0-preview5 milestone on May 4, 2026
  3. BrennanConroy commented on May 13, 2026

    @BrennanConroy
    Member

    There is a permanent ~5-8% regression likely caused by dotnet/runtime#120769 (there was some noise here too but consistently getting 5% or 8% depending on which scenario you test). @vcsjones in case you have ideas for how to fix the regression, or if this is something we expected and have to live with.

    It's a bit hard to narrow the commit range here because there was ~1 week of no builds from the VMR at this time, but dotnet/runtime#120769 is the most likely candidate since it affects hashing.

  4. vcsjones commented on May 13, 2026

    @vcsjones
    Member

    It's possible that PR introduced a regression in HMAC depending on how you are using it. Unfortunately I don't know that there is much we can do about it - this PR was an effort to move us off of deprecated OpenSSL APIs onto supported ones, and the deprecated ones are not FIPS compliant, which was the motivating factor to get off of the old ones.

    • If you are using instance based HMAC, either by creating instances HMACSHA123 or IncrementalHash, you are using the new OpenSSL APIs.
    • If you are using one-shots, like HMACSHA512.HashData then you are not using new OpenSSL APIs as the one-shots moved years ago.

    Some questions

    1. Where is the actual source for the benchmark?
    2. What OS and Target Framework are the benchmarks for?
    3. What version of OpenSSL is on the box?

    Some ways to win some back perf

    1. Use the SP800108HmacCounterKdf that is built in to the runtime (and consider using Microsoft.Bcl.Cryptography for downlevel support as well) inside of DataProtection, if that is in the anti-forgery path.
    2. Test against OpenSSL 3.5, if possible. If the benchmarks are being done against OpenSSL 3.0, it's possible it got better in 3.3 or later.
    3. Use IncrementalHash instead of new HMACSHA256() or new HMACSHA512(). The latter two do a little extra bookkeeping that IncrementalHash does not need to.
  5. BrennanConroy commented on May 13, 2026

    @BrennanConroy
    Member

    Where is the actual source for the benchmark?

    The actual source for the benchmark is at https://github.com/aspnet/Benchmarks/blob/main/src/BenchmarksApps/Antiforgery/Program.cs although that's not particularly interesting.
    https://github.com/dotnet/aspnetcore/blob/main/src/DataProtection/DataProtection/src/SP800_108/ManagedSP800_108_CTR_HMACSHA512.cs#L69 is probably more interesting as that's the callsite for hmac.

    What OS and Target Framework are the benchmarks for?

    Linux, 11.0.

    What version of OpenSSL is on the box?

    I'll need to check on that.

    Use the SP800108HmacCounterKdf that is built in to the runtime (and consider using Microsoft.Bcl.Cryptography for downlevel support as well) inside of DataProtection, if that is in the anti-forgery path.

    Looks like you made that comment before and it was claimed to be slow. #59424 (review)


    AI summary from looking at traces of before and after (I can also provide the traces offline if interested):
    Module-Level CPU Shift

    Module Baseline Experiment Δ
    System.Security.Cryptography 5.3% 13.8% +8.5% ❌
    Interop+Crypto (P/Invoke wrappers) 0.5% 7.6% +7.1% ❌
    [Native/Unknown] (unresolved native) 6.6% 0% −6.6% ✅ (now attributed)
    Microsoft.AspNetCore.DataProtection 4.4% 4.6% same

    The [Native/Unknown] category in baseline = the old lean HMAC_* native calls that the profiler couldn't attribute to
    managed frames. In the experiment, those native calls now route through more managed wrapper code in Interop+Crypto,
    making them visible but slower.

    ManagedAuthenticatedEncryptor.Encrypt — Caller-Callee Comparison

    Inclusive time: 15.6% → 17.8% (+2.2 percentage points = +8.8% relative)

    Callee Baseline Experiment Notes
    ?!? (native HMAC_*) 6.6% — Old fast path: single native call │
    Interop+Crypto.HmacOneShot — 3.1% New EVP_MAC P/Invoke
    Interop+Crypto.CryptoNative_GetRandomBytes (in ?!?) 2.8% IV generation (was hidden)
    Interop+Crypto.EvpCipherCreate — 1.0% 🆕 Context creation overhead
    SP800_108 DeriveKeys 3.6% 3.8% Same
    Interop+Sys.Malloc — 0.2% 🆕 Native malloc for OSSL_PARAM
    Interop+Crypto.EvpMdSize — 0.1% 🆕 Digest size query
    SafeHandle.ReleaseHandle 0.4% 0.6% +26% more handles to dispose

    Root Cause Breakdown

    The old HMAC_* path was a single lean native call (6.6% total, unresolvable). The new EVP_MAC path decomposes into:

    1. More managed-native transitions — HmacOneShot wraps EVP_MAC_CTX_new + EVP_MAC_init + EVP_MAC_update +
      EVP_MAC_final + EVP_MAC_CTX_free into one call, but with more marshalling
    2. EvpCipherCreate (1.0%) — creating EVP_MAC contexts per operation (provider lookup, OSSL_PARAM construction,
      string-based algorithm resolution)
    3. Malloc (0.2%) — native heap allocation for OSSL_PARAM arrays that didn't exist before
    4. More SafeHandle churn — additional handles created/disposed per crypto operation
    5. EvpMdSize (0.1%) — querying message digest sizes dynamically vs. the old pre-resolved EVP_MD* pointe
  6. vcsjones commented on May 13, 2026

    @vcsjones
    Member

    Looks like you made that comment before and it was claimed to be slow.

    It's possible it's faster than what EVP_MAC provides now. It's also FIPS compliant. Hand-rolling SP800-108 / KBKDF is not FIPS compliant.

    HmacOneShot wraps EVP_MAC_CTX_new + EVP_MAC_init + EVP_MAC_update +
    EVP_MAC_final + EVP_MAC_CTX_free into one call, but with more marshalling

    I don't understand this. The one shots have not changed from that dotnet/runtime PR.

  7. modified the milestones: 11.0-rc1, 11.0-rc2 on Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions