Neu in .NET 8.0 [33]: Erweiterung des AOT-Compilers
Der AOT-Compiler kann auch Webservices und Hintergrunddienste übersetzen, aber mit einigen Einschränkungen.
- Dr. Holger Schwichtenberg
Mit .NET 7.0 liefert Microsoft erstmals einen Ahead-of-Timer-Compiler (AOT), der es erlaubt, .NET-Anwendungen komplett in Maschinencode ohne Just-in-Time-Kompilierung zur Laufzeit auszuliefern. Der "Native AOT" genannte Compiler konnte in .NET 7.0 jedoch nur Konsolenanwendungen ĂĽbersetzen.
Seit .NET 8.0 sind nun zusätzlich auch folgende Anwendungsarten beim AOT-Compiler möglich:
- Hintergrunddienste (Worker Services)
- gRPC-Dienste
- WebAPIs mit Einschränkungen: Bei den WebAPIs ist lediglich das "Minimal WebAPI" genannte Modell möglich, mit JSON-Serialisierung via
System.Text.Json
im Source-Generator-Modus.
Weitere Einschränkungen zeigt folgende Abbildung:
Hinweis: Native AOT funktioniert weiterhin dort nicht, wo es am nötigsten wäre, um die Startzeit und den RAM-Bedarf zu verringern: Windows Forms und WPF.
Den Source Generator in System.Text.Json
hat Microsoft ausgebaut, sodass er nun fast alle Konfigurationsoptionen wie der Reflection-basierte Modus kennt. Zudem funktioniert der Source-Generator jetzt zusammen mit den Init Only Properties aus C# 9.0 und den Required Properties aus C# 11.0. Den alten Reflection-Modus kann man durch eine Projekteinstellung komplett deaktivieren. Den Modus prĂĽft die Bedingung
if (JsonSerializer.IsReflectionEnabledByDefault) { … }
Neue Native AOT-Option in Projektvorlagen
Neu in .NET 8.0 ist auch, dass es bei einigen Projektvorlagen nun direkt möglich ist, den AOT-Compiler mit der Kommandozeilenoption —aot
oder mit einem Häkchen in Visual Studio zu aktivieren:
- Konsolenanwendung:
dotnet new console –aot
- Worker Service:
dotnet new worker –aot
- gRPC:
dotnet new grpc –-aot
Bei der Projektvorlage für ASP.NET Core WebAPIs (Kurzname webapi) gibt es keine Option —aot
und kein Häkchen in Visual Studio. Hier hat sich Microsoft entschlossen, eine eigene Projektvorlage zu bauen "ASP.NET Core WebAPI (native AOT)" mit Kurznamen webapiaot. Die verwendet auch nicht das bisher in der WebAPI-Projektvorlage übliche Beispiel mit Wetterdaten, sondern eine Aufgabenliste.
Unterschiede zum normalen Minimal WebAPI-Template sind:
WebApplication.CreateSlimBuilder()
stattCreateBuilder()
- JSON-Serialisierung via Source-Generator
Folgender Code liefert eine Aufgabenliste statt einer Wettervorhersage:
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
{
}
Hinweis: Alternativ kann man den Native AOT Compiler auch wie bisher nachträglich per Tag in der Projektdatei aktivieren:
<PublishAot>true</PublishAot>
und konfigurieren:
<IlcOptimizationPreference>Speed</IlcOptimizationPreference>
oder:
<IlcOptimizationPreference>Size</IlcOptimizationPreference>
Auch bei dotnet publish
lässt sich Native AOT noch aktivieren:
dotnet publish -r win-x64 -c Release -p:PublishAOT=true
Warnungen bei inkompatiblem Code
Wer den AOT-Compiler für ein ASP.NET-Core-Projekt aktiviert, erhält seit .NET 8.0 Warnungen beim Aufruf von Methoden, die nicht kompatibel mit dem AOT-Compiler sind:
Native AOT fĂĽr Apple-Betriebssysteme
Microsoft ermöglicht es seit .NET 8.0, .NET-Anwendungen für iOS, Mac Catalyst und tvOS mithilfe des neuen .NET-Native-AOT-Compilers zu kompilieren. Diese Möglichkeit gibt es sowohl für Apps, die auf diese Plattformen beschränkt sind (.NET for iOS), als auch für das .NET Multi-Platform App UI (.NET MAUI). Dadurch laufen die Anwendungen nicht mehr auf Mono, und die App-Pakete für ".NET for iOS" werden spürbar kompakter. Hingegen verzeichnen die App-Pakete für .NET MAUI eine Zunahme in ihrer Größe.
In einem Blogeintrag bestätigt Microsoft, dass die Firma das Problem erkannt hat und aktiv an einer Lösung arbeitet, die zu einem Größenvorteil von etwa 30 Prozent führen soll.
Mögliche und nicht mögliche Operationen bei AOT
Datenbankzugriffe sind beim AOT-Compiler weiterhin nicht mit dem Objekt-Relationalen Mapper Entity Framework Core möglich, da dieser immer noch Laufzeitkompilierung verwendet. Gleiches gilt für den zweitwichtigsten OR-Mapper der .NET-Welt, den Micro-ORM Dapper. In AOT-kompilierten Anwendungen können Entwicklerinnen und Entwickler derzeit nur DataReader
, DataSet
und Command-Objekte aus ADO.NET oder das GitHub-Projekt NanORM verwenden.
Auf der Online-Konferenz betterCode() .NET 9.0 am 19. November 2024 von iX und dpunkt.verlag präsentieren .NET-Experten von www.IT-Visions.de (u.a. der Autor dieses Blogbeitrags) den fertigen Stand von .NET 9.0 anhand von Praxisbeispielen. Dazu zählen die Neuerungen in .NET 9.0 SDK, C# 13.0, ASP.NET Core 9.0, Blazor 9.0, Windows Forms 9.0, WPF 9.0, WinUI, .NET MAUI 9.0 und die Integration von Künstlicher Intelligenz in .NET-Anwendungen. Das Programm bietet sechs Vorträge, eine Diskussion und sechs Workshops.
Bis zum 22. Oktober sind Tickets zum Frühbucherpreis erhältlich.
Folgendes ist mit Native AOT auch in .NET 8.0 nicht möglich, selbst wenn man eine der oben aufgeführten Anwendungsarten erstellt:
- Laufzeitcodegenerierung (Reflection Emit)
- Dynamisches Nachladen von Assemblies (Add-Ins/Plug-Ins)
- Component Object Model (COM)
- Windows Runtime-APIs (WinRT)
- Windows Management Instrumentation (WMI)
- Zugriff auf Active Directory Services
- C++/CLI
- AOT mit WebAPIs in den Internet Information Services (IIS)
- Entity Framework Core
- Dapper
- JSON-Serialisierung mit JSON.NET (Newtonsoft JSON)
- AutoMapper und viele andere Drittanbieterbibliotheken
Möglich sind dagegen unter anderem
- Reguläre Ausdrücke
- Dateisystemzugriffe
- JSON-Serialisierung mit System.Text.Json
- NET
- NanORM
- Dependency Injection mit Microsoft Dependency Injection-Container (
Microsoft.Extensions.DependencyInjection
) undAutoFac
Performance von Native AOT
FĂĽr .NET 8.0 hat Microsoft Zahlen herausgegeben, welche Auswirkungen der Native-AOT-Compiler auf WebAPIs hat. Man sieht in der Grafik Folgendes:
- Die Größe des Kompilats, der RAM-Bedarf – insbesondere auf Linux – und die Startdauer werden wesentlich geringer.
- Die AusfĂĽhrungsgeschwindigkeit sinkt aber leider auch etwas, denn der Native-AOT-kompilierte Code schafft weniger Requests per Second (RPS).
(rme)