With .NET 7.0, Microsoft is providing an Ahead-of-Time compiler (AOT) for the first time, which allows .NET applications to be delivered entirely in machine code without just-in-time compilation at runtime. However, the compiler, called “Native AOT”, can only compile console applications in .NET 7.0.
Advertisement
Dr. Holger Schwittenberg is the technical director of the expert network www.IT-Visions.de, which supports numerous medium-sized and large companies through consulting and training as well as software development with 53 renowned experts. Through his appearances at numerous national and international conferences as well as over 90 expert books and over 1,500 expert articles, Holger Schwittenberg is one of the best-known experts for .NET and Web technologies in Germany.
Since .NET 8.0, the following types of applications are now also possible with the AOT compiler:
- Background Services (Worker Services)
- gRPC Services
- WebAPI with limitations: With WebAPI, only a model called “minimal WebAPI” is possible, which includes JSON serialization
System.Text.Json
In source generator mode.
The following figure shows further restrictions:
ASP.NET Core features supported in Native AOT in .NET 8.0
(Picture: Microsoft,
Note: Native AOT still doesn’t work where it’s needed most to reduce boot time and RAM requirements: Windows Forms and WPF.
in the source generator System.Text.Json
Microsoft has extended it so that it now knows almost all configuration options, such as reflection-based mode. In addition, the source generator now works together with the Init Only properties from C# 9.0 and the Required properties from C# 11.0. The old reflection mode can be completely deactivated using a project setting. Checks the mode state
if (JsonSerializer.IsReflectionEnabledByDefault) { … }
New Native AOT option in project templates
What is new in .NET 8.0 is that for some project templates it is now possible to use the AOT compiler directly with a command line option —aot
Or activate with a checkmark in Visual Studio:
- Console application:
dotnet new console –aot
- Worker service:
dotnet new worker –aot
- gRPC:
dotnet new grpc –-aot
The –aot parameter exists for dotnet new .
(Image: Screenshot (Holger Schwittenberg))
In Visual Studio, the gRPC Services project template provides a basic AOT option.
(Image: Screenshot (Holger Schwittenberg))
There is no option for ASP.NET Core WebAPI (short name WebPI) project template —aot
And there is no check mark in Visual Studio. Here Microsoft decided to create its own project template “ASP.NET Core WebAPI (Native AOT)” with the abbreviation WebAPIOT. It does not use the example with weather data that was used in the first WebAPI project template, but uses a task list.
One of the WebAPI project templates in Visual Studio is for native AOT.
(Image: Screenshot (Holger Schwittenberg))
The differences to the normal Minimal WebAPI template are:
WebApplication.CreateSlimBuilder()
instead ofCreateBuilder()
- JSON serialization via source generator
The following code returns a task list instead of a weather forecast:
using System.Text.Json.Serialization;
namespace MinimalWebAPI_AOT;
public class Program
{
public static void Main(string() args)
{
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
var app = builder.Build();
var sampleTodos = new Todo() {
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new(4, "Clean the bathroom"),
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
};
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
app.Run();
}
}
public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);
(JsonSerializable(typeof(Todo())))
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}
Note: Alternatively, you can also activate the native AOT compiler via a tag later in the project file, as before:
true
and configure:
Speed
Or:
Size
but also dotnet publish
Native AOT can still be activated:
dotnet publish -r win-x64 -c Release -p:PublishAOT=true
inconsistent code warnings
Since .NET 8.0, anyone who activates the AOT compiler for an ASP.NET Core project will receive warnings when calling methods that are not compatible with the AOT compiler:
The warning indicates that calling AddControllers() to enable the Model-View-Controller framework is not possible with an ahead-of-timer compiler.
(Image: Screenshot (Holger Schwittenberg))
Native AOT for Apple operating systems
Since .NET 8.0, Microsoft has made it possible to compile .NET applications for iOS, Mac Catalyst and tvOS using the new .NET Native AOT compiler. This option is available for both apps limited to these platforms (.NET for iOS) and .NET Multi-Platform App UI (.NET MAUI). As a result, applications no longer run on Mono, and app packages for “.NET for iOS” become noticeably more compact. On the other hand, the size of app packages for .NET MAUI is increasing.
in a blog post Microsoft confirms that the company has recognized the issue and is actively working on a solution that should result in massive gains of around 30 percent.
The table shows the native AOT reduction in app package size.
(Picture: Microsoft,
Possible and impossible operations in AOT
Database access with the AOT compiler using the object-relational mapper Entity Framework Core is still not possible, as it still uses runtime compilation. The same applies to the second most important OR mapper in the .NET world Micro ORM Dapper. In AOT-compiled applications, developers can currently only do this DataReader
, DataSet
and the Command object from ADO.NET or GitHub project nanoRM Use.
But Online Conference BetterCode() .NET 9.0 On November 19, 2024 by iX and dpunkt.verlag, .NET experts from www.IT-Visions.de (including the author of this blog post) will present a finished version of .NET 9.0 using practical examples. These include the .NET 9.0 SDK, C# 13.0, ASP.NET Core 9.0, Blazor 9.0, Windows Forms 9.0, WPF 9.0, WinUI, innovations in .NET MAUI 9.0 and the integration of artificial intelligence into .NET applications. Program Offers six lectures, one discussion, and six workshops.
Tickets are available until October 22 Available at an introductory price,
The following is not possible with native AOT in .NET 8.0, even if you build one of the types of applications listed above:
- Runtime code generation (reflection emission)
- Dynamic reloading of assemblies (add-ins/plug-ins)
- Component Object Model (COM)
- Windows Runtime API (WinRT)
- Windows Management Instrumentation (WMI)
- Access to Active Directory Services
- C++/CLI
- AOT with WebAPI in Internet Information Services (IIS)
- Entity Framework Core
- commercial
- JSON Serialization with JSON.NET (Newtonsoft JSON)
- AutoMapper and many other 3rd party libraries
However, things other than that are possible
- regular expression
- File system accesses
- JSON serialization with System.Text.Json
- Net
- NanoRM
- Dependency Injection with Microsoft Dependency Injection Container (
Microsoft.Extensions.DependencyInjection
) AndAutoFac
Native AOT performance
For .NET 8.0, Microsoft has released statistics showing the impact of the native AOT compiler on WebAPI. You can see the following in the graphic:
- Compilation size, RAM requirements – especially on Linux – and startup time are significantly reduced.
- Unfortunately, the execution speed also decreases somewhat because the native AOT-compiled code makes fewer requests per second (RPS).
Shows the impact of the original AOT compiler on graphic performance.
(Image: Microsoft)
(RME)