Ein erster Blick auf die Ahead-of-Time-Kompilierung in .NET 7.0

.NET 7 bringt den seit langem geplante AOT-Compiler. Ein Vergleich mit dem JIT-Compiler gibt einen ersten Eindruck vom Speicherbedarf und den Einschränkungen.

Lesezeit: 3 Min.
In Pocket speichern
vorlesen Druckansicht Kommentare lesen 8 Beiträge
Von
  • Dr. Holger Schwichtenberg

In .NET 7.0 soll nun endlich der schon lange angekündigte allgemeine Ahead-of-Time-Compiler (AOT) für .NET-Anwendungen erscheinen. Bisher gibt es in .NET ja nur AOT für Blazor WebAssembly und .NET auf iOS sowie für andere Anwendungsarten die sogenannten Ready-to-Run-Images, bei denen Native Code zusammen mit Intermediate Language in einer Assembly steckt, also weiterhin ein Just-in-Time-Compiler notwendig ist.

Wer sich nun schon auf das "Native AOT" in .NET 7 freut, um die (oft lästige) Startzeit von .NET-basierten Desktopanwendungen mit WPF und Windows Forms zu reduzieren, beachte, dass Microsoft im Zuge der Veröffentlichung der Preview 3 darauf hingewiesen hat, dass Native AOT in .NET 7 vor allem für native Libraries und Konsolenanwendungen geplant ist.

Schauen wir mal wir am anhand einer Konsolenanwendung, wie sich AOT auswirkt. Im folgenden Bild wurde sie einmal klassisch kompiliert mit .NET im Zusammenspiel mit dem Just-in-Time-Compiler, während sie das andere Mal mit dem AOT-Compiler zur Entwicklungszeit in Machinencode übersetzt wurde.

Der AOT-kompilierte Code benötigt weniger Speicher als, ist aber mit Einschränkungen verbunden.

Im letzteren Fall (rechts im Bild) entsteht immer eine Self-Contained Application (SCA), die schon die notwendigen Teile der Laufzeitumgebung und Klassenbibliotheken mit sich bringt. Im ersten Fall (links im Bild) wurde zur Vergleichbarkeit auch der SCA-Modus verwendet. Die Übersetzung erfolgt also beide Mal mit:

dotnet publish -r win-x64 -c Release --self-contained \
-p:PublishSingleFile=true

Für AOT muss man derzeit das Paket Microsoft.DotNet.ILCompiler hinzubinden:

<PackageReference
  Include="Microsoft.DotNet.ILCompiler"
  Version="7.0.0-*">

Dieses Paket gibt es noch nicht bei NuGet.org, sondern bei einem alternativen NuGet-Feed..

Das Kompilieren mit AOT umfasst dann auch Trimming (also Tree Shaking) und dauert deutlich länger.

Schauen wir auf das Ergebnis in der Abbildung, stellen wir Folgendes fest:

  • Das AOT-Kompilat ist deutlich kleiner (41.0 MB statt 70.5 MB),
  • es benötigt weniger RAM (9.3 MB statt 15.0 MB),
  • es kennt das Konzept einer Assembly (Location und DateTime lassen sich nicht abrufen) nicht und
  • im AOT-Kompilat kann man reguläre Ausdrücke verwenden (auch mit RegexOptions.Compiled), aber keine Codegenerierung zur Laufzeit (Reflection Emit) und keinen Assembly Load Context zum Nachladen von Add-Ins/Plug-Ins.

Diese Demo habe ich übrigens vorbereitet für meine .NET 7-Keynotes auf den Madgeburger Developer Days am 17.5.2022 und beim Infotag Online am 31.5.2022.

(rme)