.NET 6 vs .NET 5: up to 40% speedup!
A year ago I wrote a post comparing .NET 5 performance with its predecessor on Fusion performance tests, and honestly, I was quite impressed by the performance improvements in .NET 5. This year is no different: .NET 6 is truly the fastest .NET yet.
First, let’s look at the same test I ran last year at first:
It’s Fusion’s “Caching” sample, which uses EF Core and ASP.NET Core. You can run it by cloning https://github.com/servicetitan/Stl.Fusion.Samples and starting Run-Sample-Caching.cmd
or Run-Sample-Caching-Net50.cmd
Besides that, all .NET 6.0 tests mentioned here were run with PGO enabled:
A brief description of what above tests do:
- Tests producing 20M+ operations/s (#1, #3) are mainly constrained by Fusion’s logic, Castle.DynamicProxy, and overall, it’s ~ mostly a cache key computation and lookup logic. Almost every iteration ends up with a cache hit there.
- Tests producing <1M operations/s are constrained by either EF & SQL Server (#2, #5) or ASP.NET Core (#4 — it’s ~ the same as #5, but relying on Fusion’s caching features).
So what do we see here:
- Caching / tight loop tests get up to 30% speedup
- Test #4, which basically adds Fusion cache to a regular web API, gets 15% speedup with .NET 6
- “Typical” HTTP pipeline test (HttpClient hitting ASP.NET Core controller that hosts a CRUD style EF Core service) gets ~ 4.5% speedup.
And interestingly, the same pattern is easy to see on performance test in Fusion test suite:
You can run it by cloning https://github.com/servicetitan/Stl.Fusion and typing:
Top test set is exactly the same as the bottom one, the only difference is that it relies on Fusion’s compute service instead of a regular one, i.e. it heavily benefits of Fusion’s transparent caching logic.
So in terms of what happens under the hood,
- Top tests mostly compute cache keys, hash them, acquire async locks, and run
ConcurrentDictionary
lookups - Bottom tests actually run SQL commands — mostly
SELECT
-s fetching a single row.
And it’s clear that PGO in .NET 6 shines in the first case, so in-process caching definitely brings more advantages with .NET 6.
As for the second category of tests, even ~ 5% speedup is quite impressive for a code which speed is mostly constrained by external service (PostgreSQL or SQL Server). And benchmarks with InMemory EF Core provider (which is also a .NET library) prove this by showing ~ 14–15% speedup.
The gist is: .NET 6 with PGO enabled may bring you:
- +30–40% speed on tight loops & cache-friendly logic
- +15% for an average code that doesn’t depend on networking & IO
- +5% for a typical web service that mostly depends on networking & IO.
I plan to share a similar comparison w/ GCBurn (my garbage collection & allocation performance test) and the code I used to compare SIMD-accelerated logic on C# & C++. But again, it’s absolutely clear that .NET 6 is truly the fastest .NET yet, so huge thanks to everyone who made this possible!
P.S. My 3-month-old stealth startup is hiring a full-stack developer. If you know .NET really well and eager to use a cutting-edge real-time tech stack (Blazor, Fusion) to redefine the meaning of one of our daily activities, please PM me :)