Jede .NET-App, die Sie bisher gebaut haben, wird zweimal übersetzt: beim Build in die Zwischensprache IL, beim Start und während des Laufs vom JIT in Maschinencode. Das kostet Startzeit, und das Image muss die ganze Laufzeit mitbringen. Native AOT (ahead of time) übersetzt beim Veröffentlichen gleich in Maschinencode für ein Betriebssystem und einen Prozessor, nimmt nur den Code mit, der wirklich erreicht wird, und liefert eine einzige ausführbare Datei ohne .NET daneben. Die Lektionen 3.12.4 und davor haben vorbereitet, was dafür nötig ist: Quellgeneratoren statt Reflexion. In dieser Lektion veröffentlichen Sie einen kleinen Dienst mit Native AOT, messen, was es bringt, und entscheiden, wo es in die Kladde passt und wo nicht.
Neu in dieser Lektion:
| Image | wofür |
|---|---|
mcr.microsoft.com/dotnet/sdk:10.0-noble-aot |
das SDK mit den Werkzeugen für Native AOT unter Linux; nur zum Bauen |
mcr.microsoft.com/dotnet/runtime-deps:10.0-noble-chiseled |
das kleinste Image zum Ausführen: nur die Bibliotheken des Systems, ohne .NET, ohne Shell |
Was Native AOT bringt und was es kostet
Was es bringt (Microsoft nennt dieselben drei Punkte):
- Schneller Start. Kein JIT beim Start, keine Laufzeit, die erst geladen werden muss. Das zählt dort, wo oft gestartet wird: beim Hochskalieren unter Last, bei einem Dienst, der auf null skaliert, bei Werkzeugen für die Kommandozeile.
- Kleinere Images. Nur die eine Datei und die Bibliotheken des Systems. Kleinere Images sind schneller gezogen und haben weniger Pakete, für die Sicherheitsmeldungen kommen können.
- Weniger Speicher, je nach App: kein JIT, keine Metadaten für Reflexion.
Was es kostet:
- Keine Codeerzeugung zur Laufzeit.
System.Reflection.Emit, Assemblys zur Laufzeit laden, Typen per Name erzeugen, alles, was erst beim Lauf entscheidet, welcher Code gebraucht wird: Das gibt es nicht. Was der Compiler beim Veröffentlichen nicht sieht, fehlt. - Kürzen ist Pflicht. Der Compiler wirft weg, was er nicht erreicht. Code, der über Reflexion auf Typen zugreift, meldet er mit Warnungen
(
IL2xxxfürs Kürzen,IL3xxxfür AOT). Eine Warnung beim Veröffentlichen heißt: Diese Stelle kann zur Laufzeit scheitern. MitTreatWarningsAsErrorswie in der Kladde bricht der Build dann ab, und das ist richtig so. - Nicht jede Bibliothek. Eine Bibliothek, die Reflexion braucht, funktioniert nicht oder nur teilweise. Bei jeder Abhängigkeit prüfen Sie, ob sie Native AOT unterstützt.
- Nicht jede Art von App. In ASP.NET Core gilt nach Learn: gRPC, Health Checks, Ratenbegrenzung, Output Caching, JWT-Anmeldung und statische Dateien werden unterstützt, Minimal APIs teilweise (mit dem JSON-Generator), SignalR teilweise. Nicht unterstützt sind MVC, Blazor Server, Sitzungen und die übrigen Anmeldeverfahren. EF Core ist nach eigener Dokumentation nur eingeschränkt und mit vorkompilierten Abfragen für Native AOT geeignet; lesen Sie den Stand vor Kursbeginn auf Learn nach.
- Ein Build je Plattform. Eine Datei für
linux-x64läuft nur unter Linux auf x64. Gebaut wird auf dem Zielsystem: Unter Windows braucht Native AOT die C++-Werkzeuge von Visual Studio, für Linux baut man am einfachsten in einem Linux-Container. Ein Native-AOT-Build über Betriebssysteme hinweg geht nicht. - Längerer Build. Das Veröffentlichen dauert ein Vielfaches, weil der ganze Code in Maschinencode übersetzt wird.
Für die Kladde heißt das schon vor jeder Messung: Die Webanwendung mit Blazor und EF Core ist kein Kandidat. Ein kleiner Dienst mit Minimal API oder gRPC, wenig Abhängigkeiten und häufigem Start ist einer.