Skip to content

    Back to articles

    5 min read

    Benchmark .NET 11 before assuming it is faster

    Treat release notes as hypotheses

    .NET 11 is in release candidate, with general availability expected in November 2026, according to Microsoft’s What’s new in .NET 11. That makes it a useful point to test runtime behavior, not a reason to assume a production service will get faster.

    The “.NET runtime” section of the .NET 11 release notes describes changes across areas such as JIT optimization and async execution. Microsoft’s performance improvements in .NET 11 shows measured results for selected benchmarks. Those results are evidence about the cases tested; they are not a forecast for a different service, with different code, traffic, data and infrastructure.

    I would begin with a question tied to a workload: does the candidate runtime improve the service behavior I care about, under conditions that resemble production? That means comparing the runtime already used by the service with the .NET 11 release candidate, while keeping application changes out of the comparison. If I change code, dependencies and runtime together, a faster result tells me very little about which change helped—or what introduced a regression.

    Compare the same service under controlled conditions

    I would use a representative service build and traffic pattern, not just a tight loop around a method that happens to look important. A microbenchmark can help isolate a suspected runtime or library change. It cannot tell me whether requests to my service are dominated by database work, serialization, network waits, queueing or some other bottleneck. The service-level test needs to reflect the paths and mix of requests that matter.

    For the comparison, I would hold the application source, dependencies, configuration, data set and infrastructure constant as far as practical. I would change the target runtime, record the SDK and runtime versions, and verify that both builds are running the intended runtime. I would also keep container base image, CPU limits, memory limits and other relevant deployment settings aligned. Otherwise, I risk measuring a changed environment rather than a changed runtime.

    Run the candidate and baseline under the same load shape, with enough warm-up for the service to reach its normal operating behavior. I would avoid running both under competing load on the same constrained host: that can make the result noisier and obscure which version handled the workload better. Repeat the test, and keep the raw measurements and environment details alongside the result. These controls are my experimental discipline, not a claim that a benchmark can reproduce every production condition.

    For example, BenchmarkDotNet’s runtime customization guidance explains how to compare benchmark jobs across runtimes. The .NET team also uses a runtime comparison in its performance improvements in .NET 11 post. A small benchmark can be a useful diagnostic, but I would not let it stand in for a service-level test.

    dotnet run -c Release -f net10.0 --filter "" --runtimes net10.0 net11.0

    That command follows the form used in Microsoft’s benchmark article; the framework versions need to match the comparison I am actually running. The important point is to make the runtime contrast explicit, not to treat a benchmark harness as a miniature production environment.

    Measure outcomes that change the decision

    I would look at latency, throughput and resource use together. Latency should include the tail, not only an average: a runtime change that improves the typical request while worsening slow requests may be a poor trade for a service with tight response-time expectations. Throughput helps show how much work the service completes under a defined load. CPU and memory help explain the cost of that work and whether a change shifts pressure elsewhere.

    I would interpret those signals against the service’s own objectives and operating constraints. If the candidate uses less CPU at the same throughput and comparable latency, that is a useful result. If it serves more requests but pushes tail latency outside an acceptable range, that is not an unqualified win. If the measurements are close to normal test variation, I would call the result inconclusive rather than manufacture a benefit from a small difference.

    The same logic applies to regressions. A change that looks worse in a single run deserves another controlled test, not an immediate verdict. If the difference persists, I would look for a workload-specific explanation: which request paths shifted, whether allocation or garbage collection behavior changed, and whether the service is now constrained by a different resource. I would use diagnostics to narrow the question, then rerun the representative workload to confirm whether the effect matters at the service boundary.

    I would also preserve a clean comparison point. First test the existing application against the candidate runtime without unrelated application edits. Then, if a code or dependency change is part of the planned upgrade, measure that as a separate comparison. Keeping those results distinct lets me explain what the runtime contributed, what the application changes contributed, and where the uncertainty remains.

    Let the result set the upgrade risk

    A performance result is only one input to a runtime upgrade. I would also check compatibility, deployment behavior, observability and the service’s rollback path. A release candidate is useful for learning, but I would not confuse a successful benchmark with production readiness. Microsoft’s release notes for .NET 11 RC 1 identify it as a release candidate; the final decision still depends on the service and its operating requirements.

    The value of testing early is that it exposes both upside and uncertainty while there is still room to investigate. A repeatable gain on representative paths gives me a reason to plan adoption and validate it further. A regression tells me where to focus compatibility or performance work. No meaningful difference may still leave other reasons to upgrade, but I would not sell the move as a performance improvement.

    I would treat .NET 11 performance as a hypothesis until the service’s own measurements support it. Release notes tell me what might change; a controlled comparison tells me whether that change earns its risk in this workload.

    Drafted with AI assistance, reviewed and edited by Ali.