Compilation ReadyToRun

Le temps de démarrage et la latence de l’application .NET peuvent être améliorés par la compilation de vos assemblys d’application au format ReadyToRun (R2R). R2R est une forme de compilation ahead-of-time (AOT).

Les fichiers binaires R2R améliorent les performances de démarrage en réduisant la quantité de travail que le compilateur juste-à-temps (JIT) doit faire lorsque votre application est chargée. Les fichiers binaires contiennent du code natif similaire à ce que la compilation JIT produirait. Cependant, les fichiers binaires R2R sont plus grands, car ils contiennent à la fois le code du langage intermédiaire (IL), qui est toujours nécessaire pour certains scénarios, et la version native du même code. R2R est disponible seulement quand vous publiez une application qui cible des environnements d’exécution spécifiques (RID), comme Linux x64 ou Windows x64.

Pour compiler votre projet au format ReadyToRun, l’application doit être publiée avec la propriété PublishReadyToRun définie sur true.

Il existe deux façons de publier votre application au format ReadyToRun :

  1. Spécifiez l’indicateur PublishReadyToRun directement dans la commande dotnet publish. Pour plus d’informations, consultez dotnet publish.

    dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true
    
  2. Spécifiez la propriété dans le projet.

    • Ajoutez le paramètre <PublishReadyToRun> à votre projet.
    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
    • Publiez l’application sans aucun paramètre spécial.
    dotnet publish -c Release -r win-x64
    

Impact de l’utilisation de la fonctionnalité ReadyToRun

La compilation anticipée a un impact complexe sur les performances des applications, ce qui peut être difficile à prédire. En règle générale, la taille d’un assembly augmente de deux à trois fois. Cette augmentation de la taille physique du fichier peut réduire les performances du chargement de l’assembly à partir du disque et augmenter la plage de travail du processus. Toutefois, en retour, le nombre de méthodes compilées au moment de l’exécution est généralement réduit considérablement. Le résultat est que la plupart des applications qui ont de grandes quantités de code reçoivent d’importants avantages en matière de performances provenant de l’activation de ReadyToRun. Les applications qui ont de petites quantités de code ne bénéficieront probablement pas d’une amélioration significative provenant de l’activation de ReadyToRun, car les bibliothèques de runtime .NET ont déjà été précompilées avec ReadyToRun.

L’amélioration de démarrage décrite ici s’applique non seulement au démarrage de l’application, mais également à la première utilisation de n’importe quel code dans l’application. Par exemple, ReadyToRun peut être utilisé pour réduire la latence de réponse de la première utilisation de l’API web dans une application ASP.NET.

Interaction avec la compilation hiérarchisée

Le code généré à l’avance n’est pas aussi optimisé que le code généré par le JIT. Pour résoudre ce problème, la compilation hiérarchisée remplace les méthodes ReadyToRun couramment utilisées par des méthodes générées par JIT.

Comment l’ensemble d’assemblys précompilés est-il choisi ?

Le Kit de développement logiciel (SDK) précompile les assemblys distribués avec l’application. Pour les applications autonomes, cet ensemble d’assemblys inclut l’infrastructure. Les fichiers binaires C++/CLI ne sont pas éligibles à la compilation ReadyToRun.

Pour exclure des assemblys spécifiques du traitement ReadyToRun, utilisez la liste <PublishReadyToRunExclude>.

<ItemGroup>
  <PublishReadyToRunExclude Include="Contoso.Example.dll" />
</ItemGroup>

Comment l’ensemble de méthodes à précompiler est-il choisi ?

Le compilateur tente de précompiler autant de méthodes que possible. Toutefois, pour diverses raisons, il n’est pas prévu que l’utilisation de la fonctionnalité ReadyToRun empêche l’exécution du JIT. Ces raisons peuvent inclure, mais sans s’y limiter :

  • Utilisation de types génériques définis dans des assemblys distincts.
  • Interopérabilité avec du code natif.
  • L’utilisation de valeurs intrinsèques matérielles que le compilateur ne peut pas prouver est sûre sur une machine cible.
  • Certains modèles IL inhabituels.
  • Création d’une méthode dynamique via la réflexion ou LINQ.

Génération de symboles à utiliser avec des profileurs

Lors de la compilation d’une application avec ReadyToRun, les profileurs peuvent nécessiter des symboles pour examiner les fichiers ReadyToRun générés. Pour activer la génération de symboles, spécifiez la propriété <PublishReadyToRunEmitSymbols>.

<PropertyGroup>
  <PublishReadyToRunEmitSymbols>true</PublishReadyToRunEmitSymbols>
</PropertyGroup>

Ces symboles sont placés dans le répertoire de publication et, pour Windows, ils ont une extension de fichier .ni.pdb et, pour Linux, ils ont une extension de fichier .r2rmap. Ces fichiers ne sont généralement pas redistribués aux clients finaux, mais sont généralement stockés dans un serveur de symboles. En général, ces symboles sont utiles pour le débogage des problèmes de performances liés au démarrage d’applications, car la compilation hiérarchisée remplace le code généré par ReadyToRun par du code généré dynamiquement. Toutefois, si vous tentez de profiler une application qui désactive la compilation hiérarchisée, les symboles seront utiles.

ReadyToRun composite

La compilation ReadyToRun normale produit des fichiers binaires qui peuvent faire l’objet d’une maintenance et d’une manipulation individuellement. À compter de .NET 6, la prise en charge de la compilation Composite ReadyToRun a été ajoutée. ReadyToRun composite compile un ensemble d’assemblys qui doivent être distribués ensemble. Cela présente l’avantage que le compilateur est en mesure d’effectuer de meilleures optimisations et réduit l’ensemble de méthodes qui ne peuvent pas être compilées via le processus ReadyToRun. Toutefois, en guise que compromis, la vitesse de compilation est considérablement réduite et la taille globale du fichier de l’application est considérablement augmentée. En raison de ces compromis, l’utilisation de ReadyToRun composite est recommandée uniquement pour les applications qui désactivent la compilation hiérarchisé ou les applications s’exécutant sur Linux qui recherchent le meilleur temps de démarrage avec déploiement autonome. Pour activer la compilation ReadyToRun composite, spécifiez la propriété <PublishReadyToRunComposite>.

<PropertyGroup>
  <PublishReadyToRunComposite>true</PublishReadyToRunComposite>
</PropertyGroup>

Notes

Dans .NET 6, ReadyToRun composite est pris en charge uniquement pour le déploiement autonome.

Restrictions d’architecture/de multiplateforme

Pour certaines plateformes du Kit de développement logiciel (SDK), le compilateur ReadyToRun est capable d’effectuer une compilation croisée pour d’autres plateformes cibles.

Les cibles de compilation prises en charge sont décrites dans le tableau ci-dessous lors du ciblage de .NET 6 et des versions ultérieures.

Plateforme du Kit de développement logiciel (SDK) Plateformes cibles prises en charge
Windows X64 Windows (X86, X64, Arm64), Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
Windows X86 Windows (X86), Linux (Arm32)
Linux X64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
Linux Arm32 Linux Arm32
Linux Arm64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
macOS X64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
macOS Arm64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)

Les cibles de compilation prises en charge sont décrites dans le tableau ci-dessous lors du ciblage de .NET 5 et ci-dessous.

Plateforme du Kit de développement logiciel (SDK) Plateformes cibles prises en charge
Windows X64 Windows X86, Windows X64, Windows Arm64
Windows X86 Windows X86, Windows Arm32
Linux X64 Linux X86, Linux X64, Linux Arm32, Linux Arm64
Linux Arm32 Linux Arm32
Linux Arm64 Linux Arm64
macOS X64 macOS X64