.NET runtime
With the release of .NET 8.0, developers can look forward to range of exciting new features and improvements that enhance performance, streamline development, and extend the capabilities of the framework. Here’s an overview of what’s new in .NET 8 and why it’s a significant upgrade for the developers.
Long-Term Support (LTS)
One of the key highlights of .NET 8 is designation of a Long Term Support (LTS) release. This means .NET 8 will receive support and maintenance for three years, providing stability and reliability for applications that require long term deployment.
Performance Enhancements
.NET 8 continues to build on performance improvements seen on the previous versions. The runtime has been optimised to deliver faster execution time and more efficient resource management. The enhancements ensures that application run more smoothly and handle larger workloads with greater efficiency.
Improved Garbage Collection
.NET 8 introduces the ability to adjust memory limits dynamically, a valuable feature for cloud-service scenarios where demand fluctuates. To remain cost-effective, services must scale their resource consumption up and down in response to changing demand. When a service detects a decrease in demand, it can now reduce its memory limit accordingly. Previously, this adjustment could fail because the garbage collector (GC) might allocate more memory than the new limit, being unaware of the change. With .NET 8, you can use the RefreshMemoryLimit() API to inform the GC of the updated memory limit, ensuring efficient resource management.
Here are some limitations to consider:
- On 32-bit platforms (e.g., Windows x86 and Linux ARM), .NET cannot establish a new heap hard limit if one isn’t already set.
- The API might return a non-zero status code, indicating the refresh failed. This can occur if the scale-down is too aggressive, leaving insufficient room for the GC to operate. In such cases, try calling GC.Collect(2, GCCollectionMode.Aggressive) to reduce current memory usage, and then attempt the refresh again.
- If you increase the memory limit beyond what the GC believes the process can handle at startup, the RefreshMemoryLimit call will succeed, but the GC will not utilize more memory than its perceived limit.
The following code snippet shows how to call the API.
GC.RefreshMemoryLimit();
You can also update certain GC configuration settings related to the memory limit. The following code snippet sets the heap hard limit to 100 mebibytes (MiB):
AppContext.SetData("GCHeapHardLimit", (ulong)100 * 1_024
* 1_024);
GC.RefreshMemoryLimit();
The API may throw an InvalidOperationException if the hard limit is invalid, such as when the heap hard limit percentage is negative, or the limit is set too low. This issue can arise if the new heap hard limit, determined by updated AppData settings or changes in the container memory limit, is lower than the already committed memory.
New Globalization Mode for Mobile Apps
Mobile apps on iOS, tvOS, and MacCatalyst can now opt into a new hybrid globalization mode that uses a lighter ICU bundle. In this hybrid mode, globalization data is sourced partially from the ICU bundle and partially from native API calls. This approach supports
all the locales available on mobile platforms.
Hybrid mode is ideal for apps that cannot function in invariant globalization mode and require cultures that were removed from the ICU data on mobile. It is also beneficial when you want to load a smaller ICU data le, as the icudt_hybrid.dat le is 34.5% smaller than the default icudt.dat file.
To use hybrid globalization mode, set the HybridGlobalization MSBuild property to true:
<PropertyGroup> <HybridGlobalization>true</HybridGlobalization> </PropertyGroup>
Be aware of the following limitations:
- Some supported APIs may exhibit different behavior.
- Not all globalization APIs are supported in hybrid mode due to
limitations of the Native API.
Source Generators for COM Interop and Configuration Binding
One of the standout features in .NET 8 is the introduction of new source generators for COM interop and configuration binding. These source generators automate the creation of interop code, reducing the amount of boilerplate code that developers need to write. This not only speeds up the development process but also reduces the likelihood of errors, resulting in more reliable and maintainable code.
COM Interop Source Generators
The new COM interop source generators simplify the process of interacting with COM
components. By automatically generating the necessary interop code, developers can easily integrate COM components into their .NET applications without the hassle of manually writing and maintaining interop code.
Configuration Binding Source Generators
In .NET 8, a source generator has been introduced for ASP.NET Core, aiming to offer configuration that is AOT and trim- friendly. This new generator serves as an alternative to the current reflection-based approach.
The source generator examines calls to Configure(TOptions), Bind, and Get to gather type information. Once enabled in a project, the compiler automatically prioritizes the generated methods over the existing reflection-based framework implementations.
No modifications to the source code are necessary to utilize the generator. It is automatically enabled in AOT-compiled web applications and when the PublishTrimmed option is true (applicable to .NET 8+ apps). For other project types, the source generator is disabled by default. However, you can activate it by setting the EnableConfigurationBindingGenerator property to true in your project file.
The following code shows an example of invoking the binder-
public class ConfigBindingSG
{
static void RunIt(params string[] args)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
IConfigurationSection section = builder.Configuration.GetSection("MyOptions");
// !! Configure call - to be replaced with source-gen'd implementation
builder.Services.Configure<MyOptions>(section);
// !! Get call - to be replaced with source-gen'd implementation
MyOptions? options0 = section.Get<MyOptions>();
// !! Bind call - to be replaced with source-gen'd implementation
MyOptions options1 = new();
section.Bind(options1);
WebApplication app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
}
public class MyOptions
{
public int A { get; set; }
public string S { get; set; }
public byte[] Data { get; set; }
public Dictionary<string, string> Values { get; set; }
public List<MyClass> Values2 { get; set; }
}
public class MyClass
{
public int SomethingElse { get; set; }
}
}
Cross-built Windows apps
Now, when developing applications that target Windows on non-Windows platforms, the resulting executable includes any specified Win32 resources, such as application icons, manifests, and version information.
Previously, applications required building on Windows to incorporate such resources. Addressing this gap in cross-building support has been a widely requested improvement, as it significantly alleviates infrastructure complexity and resource consumption.
Native AOT Support
The feature to publish as Native AOT was initially introduced in .NET 7. When you publish an application with Native AOT, it generates a fully self-contained version of your app, eliminating the need for a runtime—everything is bundled within a single file. .NET 8 introduces several enhancements to Native AOT publishing, including:
-
Adds support for the x64 and Arm64 architectures on macOS.
-
Reduces the sizes of Native AOT apps on Linux by up to 50%. The following table shows the size of a “Hello World” app published with Native AOT that includes the entire .NET runtime on .NET 7 vs. .NET 8:
|
Operating system |
.NET 7 |
.NET 8 |
|
Linux x64 (with -p:StripSymbols=true) |
3.76 MB |
1.84 MB |
|
Windows x64 |
2.85 MB |
1.77 MB |
-
Lets you specify an optimization preference: size or speed. By default, the compiler chooses to generate fast code while being mindful of the size of the application. However, you can use the <OptimizationPreference> MSBuild property to optimize specifically for one or the other.
Target iOS-like platforms with Native AOT
In .NET 8, the groundwork is laid to enable Native AOT support for iOS-like platforms. You can now develop and execute .NET iOS and .NET MAUI applications with Native AOT on the following platforms:
- ios
- iossimulator
- maccatalyst
- tvos
- tvossimulator
Initial testing indicates a significant reduction in app size on disk for .NET iOS apps that utilize Native AOT instead of Mono, with a decrease of approximately 35%. Similarly, .NET MAUI iOS apps experience up to a 50% decrease in app size on disk. Moreover, there are notable improvements in startup time, with .NET iOS apps exhibiting approximately 28% faster startup time and .NET MAUI iOS apps showing approximately 50% better startup performance compared to Mono.
It’s important to note that while these advancements are promising, the .NET 8 support for Native AOT is experimental and represents just the initial phase of this feature’s development.
Native AOT support is offered as an optional feature primarily intended for app deployment, while Mono remains the default runtime for both app development and deployment. To build and run a .NET MAUI application with Native AOT on an iOS device, follow these steps:
- Install the .NET MAUI workload using the command dotnet workload install maui.
-
Create the .NET MAUI app using the command dotnet new maui -n HelloMaui.
-
In the project file, set the MSBuild property PublishAot to true.
<PropertyGroup> <PublishAot>true</PublishAot> </PropertyGroup>
Following these steps will enable Native AOT support for your .NET MAUI application on iOS devices, enhancing performance and reducing app size.
Once you’ve set the required property, running dotnet publish as illustrated in the following example will deploy the app using Native AOT:
dotnet publish -f net8.0-ios -c Release -r ios-arm64 /t:Run
Native AOT deployment for iOS-like platforms comes with certain limitations:
- iOS Feature Compatibility: Not all iOS features are compatible with Native AOT. Some functionalities may not behave as expected when deployed with Native AOT.
- Library Compatibility: Similarly, not all libraries commonly used in iOS development are compatible with Native AOT. Some libraries may not work as intended or may require adjustments for compatibility.
- Limited Debugging Support: Managed code debugging is only supported with Mono. Debugging capabilities are limited when using Native AOT.
- Compatibility with .NET MAUI: Compatibility with the .NET MAUI framework is limited when targeting iOS-like platforms with Native AOT. Some features and functionalities may not be fully supported or may require additional configuration.
Keep these limitations in mind when developing and deploying .NET MAUI applications for iOS-like platforms with Native AOT.
AOT compilation for Android apps
In order to reduce the size of .NET and .NET MAUI applications targeting Android, they utilize profiled ahead-of-time (AOT) compilation mode during Release mode builds. Profiled AOT compilation mode impacts fewer methods compared to regular AOT compilation, aiding in size reduction.
In .NET 8, the <AndroidStripILAfterAOT> property is introduced, providing the option to opt-in for additional AOT compilation specifically for Android apps. This further decreases the size of the application, offering greater optimization for deployment on Android devices.
<PropertyGroup> <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT> </PropertyGroup>
By default, when setting AndroidStripILAfterAOT to true, it overrides the default AndroidEnableProfiledAot setting. This allows (nearly) all methods that were AOT-compiled to be trimmed, contributing to further size reduction.
Moreover, you have the option to combine profiled AOT and IL stripping by explicitly setting both properties to true. This enables a comprehensive approach to size optimization for .NET and .NET MAUI applications targeting Android platforms.
<PropertyGroup> <AndroidStripILAfterAOT>true</AndroidStripILAfterAOT> <AndroidEnableProfiledAot>true</AndroidEnableProfiledAot> </PropertyGroup>
Core and Extension Library Updates
The core and extension libraries in .NET 8 have been updated to include new features and enhancements. These updates provide developers with more tools and capabilities to build robust and feature-rich applications. The libraries have been optimized for better performance and usability, making it easier for developers to implement complex functionality with less code.