Les performances de démarrage et la taille binaire sont devenues des enjeux clés, notamment dans les contextes desktop, embarqués, et CLI. C’est pourquoi .NET 9 pousse encore plus loin le support d’AOT (Ahead-of-Time compilation) et de NativeAOT.
Cet article vous guide à travers ces technologies, leurs avantages, limitations, et mise en œuvre concrète.
🚀 Qu’est-ce que l’AOT ?
- JIT (Just-In-Time) compile à l’exécution : plus flexible, mais plus lent au démarrage.
- AOT compile tout ou partie du code à l’avance : démarrage plus rapide, comportement plus prévisible.
.NET 9 propose deux modes :
- ReadyToRun (R2R) : hybride JIT + AOT
- NativeAOT : compilation complète en code natif, sans runtime JIT du tout
📦 Pourquoi NativeAOT ?
- Démarrage instantané (pas de JIT au runtime)
- Fichiers exécutables plus petits et autonomes
- Meilleure compatibilité avec les scénarios "CLI", embarqués, ou desktop critiques
- Aucun besoin du .NET Runtime installé sur la machine
🧪 Exemple de projet NativeAOT simple
1.Créez un projet console :
dotnet new console -n HelloNative
2. Modifiez le fichier .csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<PublishAot>true</PublishAot>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
</Project>
3. Code source :
Console.WriteLine("Hello, NativeAOT!");
4.Compilation :
dotnet publish -c Release -r win-x64 --self-contained
Cela produit un exécutable .exe natif, autonome.
⚠️ Limitations actuelles de NativeAOT
- Pas de Reflection.Emit
- Dynamique limitée : Assembly.Load, Type.GetType() peuvent échouer
- Certains packages (ex. System.Text.Json SourceGenerator requis)
- Pas encore compatible avec tout ASP.NET (mais possible avec des APIs minimales)
🧠 Bonnes pratiques AOT
- Privilégier les générateurs de source (System.Text.Json, DllImportGenerator, etc.)
- Éviter l’usage dynamique ou tardif du typage
- Isoler les composants problématiques dans des sous-assemblies non-AOT
🔍 Debugging et diagnostic
- Utiliser --self-contained pour l’autonomie
- Activer les logs de trim et d’AOT avec :
dotnet publish -c Release -r win-x64 /p:IlcGenerateFullPaths=true /p:PublishTrimmed=true
- Explorer avec ILSpy, dotnet-trace, ou perfview
✅ Scénarios adaptés
- CLI utilitaires distribuables sans dépendances
- Applications desktop autoportées
- Containers légers avec démarrage instantané
- Serveurs API sans état avec performances critiques
🔚 Conclusion
NativeAOT en .NET 9 est mûr pour la production dans de nombreux scénarios. Il transforme la façon de penser les applications .NET : plus légères, plus rapides, plus prévisibles.
C’est une opportunité forte pour les développeurs qui veulent optimiser la distribution et les performances.
La possibilité de délivrer un exécutable sans JIT et sans framework nous ramène ironiquement à ce que nous savions faire "avant"... Prenez un vieux compilateur Pascal sous CP/M fin des années 70, début 80, ça faisait ça : un exécutable facile à distribuer... Il est vrai qu'en termes d'UI, d'UX et autres demandes des utilisateurs on faisait le minimum. Mais c'était simple et pratique. On aura mis 40 ans pour revenir à cette simplicité. Saluons la grande roue des innovations technologiques qui tournent vite donnant l'impression de changements incroyables, mais pour, au final, en revenir aux solutions d'il y a longtemps (comme la mode des PC pour revenir à des machines qui ne marchent pas sans Internet et des sites Web avec API, réinventant l'informatique centralisée avec ses terminaux 5250 connectés à des System/36 IBM de nos aïeux qui, au passage, doivent bien rire de là haut...).
L'informatique c'est fun alors,
Stay Tuned !