In terms of API, nothing has changed dramatically, hence no major updated to my course. But let’s geek out for low level details.
In this post, I’ll give you a brief overview of some of the cool things you can do with .NET 7 performance monitoring tools and how they compare to .NET 6. Let’s get started!
On-Stack Replacement (OSR)
One of the most impressive features of .NET 7 is on-stack replacement (OSR), which allows the runtime to change the code executed by a currently running method in the middle of its execution (that is, while it’s “on stack”). This means that long-running methods can switch to more optimized versions mid-execution without affecting correctness or functionality.
This feature complements tiered compilation, which already enables methods to be recompiled at higher optimization levels after they’ve been executed enough times. OSR takes this one step further by allowing methods that are already running to benefit from these optimizations as well.
OSR can be very useful for scenarios where methods have long-running loops or complex logic that can be optimized based on runtime feedback. For example, imagine you have a method that performs some heavy calculations on an array of data. With OSR, you can start executing this method with a less optimized version that has some instrumentation code to collect data about the array size, distribution, etc. Then, based on this data, you can switch to a more optimized version that uses vectorization, parallelization, caching, etc.
To enable OSR in your project file, simply add
<TieredOSR>true</TieredOSR> properties. You can also use environment variables or runtime configuration knobs to control OSR behavior at runtime.
Profile-Guided Optimization (PGO)
Another feature that works well with OSR is profile-guided optimization (PGO), which uses runtime profiling data to guide code generation decisions. PGO can improve performance by optimizing hot paths, reducing branch mispredictions, improving register allocation, etc.
PGO was introduced in .NET 6 as an experimental feature that required manual steps to enable and use. In .NET 7, PGO is much easier to use and works seamlessly with OSR. You just need to add
<TieredPGO>true</TieredPGO> property to your project file and let the runtime do its magic.
PGO can also instrument and optimize additional things in .NET 7, such as delegates. Delegates are widely used in .NET for callbacks, events, lambdas, etc., but they come with some overhead due to indirect calls and allocations. With PGO, the runtime can learn which delegates are frequently invoked and inline them into their callers, reducing overhead and improving performance.
Improved Code Generation for Arm64
If you’re developing applications for Arm64 devices, such as smartphones, tablets, or IoT devices, you’ll be happy to know that .NET 7 has improved code generation for this architecture.
The JIT compiler has been enhanced to produce better quality code that takes advantage of Arm64 features, such as SIMD instructions, conditional select operations, and hardware intrinsics.
These improvements can result in significant speedups for various workloads, such as math operations, string manipulation, JSON parsing, etc.
Another way to improve performance is by using native ahead-of-time (AOT) compilation, which produces a standalone executable in the target platform’s file format with no external dependencies. It’s entirely native, with no IL or JIT, and provides fast startup time and a small, self-contained deployment.
Native AOT was also introduced in.NET 6 as an experimental feature that required manual steps to enable and use.
In.NET 7, Native AOT is still experimental, but it has been improved to support more scenarios and platforms, such as Windows, Linux, macOS, iOS, Android, and WebAssembly.
To contact me, send an email anytime or leave a comment below.