Tracer des applications .NET avec PerfCollect

Cet article s’applique à : ✔️ SDK .NET Core 2.1 et versions ultérieures

En cas de problèmes de performances sur Linux, la collecte d’une trace avec perfcollect peut être utilisée pour collecter des informations détaillées sur ce qui se passe sur l’ordinateur au moment du problème de performances.

perfcollect est un script bash qui utilise Linux Trace Toolkit : nouvelle génération (LTTng) pour collecter les événements écrits à partir du runtime ou de n’importe quel EventSource ou perf pour collecter des exemples de processeur du processus cible.

Préparer votre machine

Suivez ces étapes pour préparer votre machine à collecter une trace de performance avec perfcollect.

Remarque

Si vous capturez à l’intérieur d’un conteneur, votre conteneur doit avoir les fonctionnalités appropriées. Les fonctionnalités minimales requises sont PERFMON et SYS_PTRACE. Si la capture échoue avec le jeu minimal, ajoutez la fonctionnalité SYS_ADMIN au conteneur. Pour plus d’informations sur le traçage des applications à l’intérieur de conteneurs à l’aide de PerfCollect, consultez Collecter des diagnostics dans des conteneurs.

  1. Télécharger perfcollect.

    curl -OL https://aka.ms/perfcollect
    
  2. Rendez le script exécutable.

    chmod +x perfcollect
    
  3. Installez les prérequis de traçage : il s’agit des bibliothèques de traçage réelles.

    sudo ./perfcollect install
    

    Cette opération installe les conditions préalables suivantes sur votre machine :

    1. perf : le sous-système Événements de performances Linux et l’application de collecte/visionneuse en mode utilisateur complémentaire. perf fait partie de la source du noyau Linux, mais n’est généralement pas installé par défaut.

    2. LTTng : utilisé pour capturer les données d’événement émises au moment de l’exécution par CoreCLR. Ces données sont ensuite utilisées pour analyser le comportement de divers composants runtime tels que GC, JIT et le pool de threads.

Les versions récentes de .NET Core et de l’outil de performance Linux prennent en charge la résolution automatique des noms de méthode pour le code de l’infrastructure.

Pour résoudre les noms de méthode des DLL du runtime natives (telles que libcoreclr.so), perfcollect résout les symboles pour ceux-ci lorsqu’il convertit les données, mais uniquement si les symboles de ces fichiers binaires sont présents. Pour plus d’informations, consultez la section Obtenir des symboles pour le runtime natif.

Collecter une trace

  1. Deux interpréteurs de commandes sont disponibles : l’un pour contrôler le suivi, appelé [Trace] et l’autre pour l’exécution de l’application, appelé [Application].

  2. [Trace] Démarrer la collecte.

    sudo ./perfcollect collect sampleTrace
    

    Sortie attendue :

    Collection started.  Press CTRL+C to stop.
    
  3. [Application] Configurez l’interpréteur de commandes d’application avec les variables d’environnement suivantes, ce qui permet de configurer le traçage de CoreCLR.

    export DOTNET_PerfMapEnabled=1
    export DOTNET_EnableEventLog=1
    

    Notes

    Lors de l’exécution de l’application avec .NET 7, vous devez également définir DOTNET_EnableWriteXorExecute=0 en plus des variables d’environnement précédentes. Par exemple :

    export DOTNET_EnableWriteXorExecute=0
    

    Notes

    .NET 6 se normalise sur le préfixe DOTNET_ au lieu de COMPlus_ pour les variables d’environnement qui configurent le comportement au moment de l’exécution de .NET. Toutefois, le préfixe COMPlus_ continuera à fonctionner. Si vous utilisez une version précédente du runtime .NET, vous devez tout de même utiliser le préfixe COMPlus_.

  4. [Application] Exécutez l’application : laissez-la s’exécuter aussi longtemps que nécessaire afin de capturer le problème de performances. La longueur exacte peut être aussi courte que nécessaire tant qu’elle capture suffisamment la fenêtre de temps où se produit le problème de performance que vous souhaitez examiner.

    dotnet run
    
  5. [Trace] Arrêter la collection : appuyez sur Ctrl+C.

    ^C
    ...STOPPED.
    
    Starting post-processing. This may take some time.
    
    Generating native image symbol files
    ...SKIPPED
    Saving native symbols
    ...FINISHED
    Exporting perf.data file
    ...FINISHED
    Compressing trace files
    ...FINISHED
    Cleaning up artifacts
    ...FINISHED
    
    Trace saved to sampleTrace.trace.zip
    

    Le fichier de trace compressé est maintenant stocké dans le répertoire de travail actuel.

Afficher une trace

Il existe un certain nombre d’options pour afficher la trace qui a été collectée. Les traces sont plus visibles à l’aide de PerfView sur Windows, mais elles peuvent être consultées directement sur Linux en utilisant PerfCollect ou TraceCompass.

Utiliser PerfCollect pour afficher le fichier de trace

Vous pouvez utiliser perfcollect pour afficher la trace que vous avez collectée. Pour ce faire, utilisez la commande suivante :

./perfcollect view sampleTrace.trace.zip

Par défaut, cela affiche la trace du processeur de l’application à l’aide de perf.

Pour examiner les événements collectés via LTTng, vous pouvez passer l’indicateur -viewer lttng pour voir les événements individuels :

./perfcollect view sampleTrace.trace.zip -viewer lttng

Cette opération utilise la visionneuse babeltrace pour imprimer la charge utile des événements :

# [01:02:18.189217659] (+0.020132603) ubuntu-xenial DotNETRuntime:ExceptionThrown_V1: { cpu_id = 0 }, { ExceptionType = "System.Exception", ExceptionMessage = "An exception happened", ExceptionEIP = 139875671834775, ExceptionHRESULT = 2148734208, ExceptionFlags = 16, ClrInstanceID = 0 }
# [01:02:18.189250227] (+0.020165171) ubuntu-xenial DotNETRuntime:ExceptionCatchStart: { cpu_id = 0 }, { EntryEIP = 139873639728404, MethodID = 139873626968120, MethodName = "void [helloworld] helloworld.Program::Main(string[])", ClrInstanceID = 0 }

Utiliser PerfView pour ouvrir le fichier de trace

Pour afficher une vue agrégée de l’exemple du processeur et des événements, vous pouvez utiliser PerfView sur un ordinateur Windows.

  1. Copiez le fichier trace.zip de Linux vers une machine Windows.

  2. Téléchargez PerfView à partir de https://aka.ms/perfview.

  3. Exécutez PerfView.exe

    PerfView.exe <path to trace.zip file>
    

PerfView affiche la liste des vues prises en charge en fonction des données contenues dans le fichier de trace.

  • Pour les investigations sur le processeur, choisissez Piles de processeur.

  • Pour obtenir des informations détaillées sur le GC, choisissez GCStats.

  • Pour les informations JIT par processus/module/méthode, choisissez JITStats.

  • S’il n’existe pas de vue pour les informations dont vous avez besoin, vous pouvez essayer de rechercher les événements dans l’affichage événements bruts. Choisissez Événements.

Pour plus d’informations sur l’interprétation des affichages dans PerfView, consultez les liens d’aide dans la vue elle-même ou, dans la fenêtre principale de PerfView, choisissez Aide->Guide des utilisateurs.

Notes

Les événements écrits via l’API System.Diagnostics.Tracing.EventSource (y compris les événements de l’infrastructure) n’apparaissent pas sous leur nom de fournisseur. Au lieu de cela, ils sont écrits en tant qu’EventSourceEventévénements sous Microsoft-Windows-DotNETRuntime le fournisseur et leurs charges utiles sont sérialisées au format JSON.

Notes

Si vous observez des cadres [unknown] /memfd:doublemapper dans les noms de méthode et les piles d’appels, définissez DOTNET_EnableWriteXorExecute=0 avant d’exécuter l’application que vous tracez avec perfcollect.

Utiliser TraceCompass pour ouvrir le fichier de trace

Eclipse TraceCompass est une autre option que vous pouvez utiliser pour afficher les traces. TraceCompass fonctionne également sur les machines Linux, de sorte que vous n’avez pas besoin de déplacer votre trace sur une machine Windows. Pour utiliser TraceCompass pour ouvrir votre fichier de trace, vous devez décompresser le fichier.

unzip myTrace.trace.zip

perfcollect enregistre la trace LTTng collectée dans un format de fichier CTF dans un sous-répertoire du lttngTrace. Plus précisément, le fichier CTF se trouve dans un répertoire qui ressemble à lttngTrace/auto-20201025-101230\ust\uid\1000\64-bit\.

Vous pouvez ouvrir le fichier de trace CTF dans TraceCompass en sélectionnant File -> Open Trace et sélectionnez le fichier metadata.

Pour plus d’informations, consultez cette TraceCompass documentation.

Obtenir des symboles pour le runtime natif

La plupart du temps, vous êtes intéressé par votre propre code, queperfcollect résout par défaut. Parfois, il est utile de voir ce qui se passe à l’intérieur des DLL .NET (ce qui est le sujet de la dernière section), mais parfois ce qui se passe dans les DLL de runtime natives (généralement libcoreclr.so), est intéressant. perfcollect résout les symboles pour ceux-ci lorsqu’il convertit ses données, mais seulement si les symboles de ces DLL natives sont présents (et sont à côté de la bibliothèque pour laquelle ils sont destinés).

Il existe une commande globale appelée dotnet-symbol qui effectue cette opération. Pour utiliser dotnet-symbol pour obtenir des symboles d’exécution natifs :

  1. Installez dotnet-symbol :

    dotnet tool install -g dotnet-symbol
    
  2. Téléchargez les symboles. Si votre version installée du runtime .NET Core est 2.1.0, la commande à effectuer est la suivante :

    mkdir mySymbols
    dotnet symbol --symbols --output mySymbols  /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0/lib*.so
    
  3. Copiez les symboles à l’emplacement approprié.

    sudo cp mySymbols/* /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0
    

    Si cette opération ne peut pas être effectuée car vous n’avez pas accès en écriture au répertoire approprié, vous pouvez utiliser perf buildid-cache pour ajouter les symboles.

Après cela, vous devez obtenir des noms symboliques pour les dll natives lorsque vous exécutez perfcollect.

Collecter dans un conteneur Docker

Pour plus d’informations sur l’utilisation de perfcollect dans les environnements de conteneur, consultez Collecter les diagnostics dans les conteneurs.

En savoir plus sur les options de collection

Vous pouvez spécifier les indicateurs facultatifs suivants avec perfcollect pour mieux répondre à vos besoins de diagnostic.

Collecter pendant une durée spécifique

Lorsque vous souhaitez collecter une trace pour une durée spécifique, vous pouvez utiliser l’option -collectsec suivie d’un nombre spécifiant le nombre total de secondes pour lesquelles collecter une trace.

Collecter les traces threadtime

La spécification de -threadtime avec perfcollect vous permet de collecter des données d’utilisation du processeur par thread. Cela vous permet d’analyser où chaque thread passait son temps processeur.

Collecter des traces pour les performances de la mémoire managée et du récupérateur de mémoire

Les options suivantes vous permettent de spécifiquement collecter les événements GC à partir du runtime.

  • perfcollect collect -gccollectonly

Collectez uniquement un ensemble minimal d’événements de collection GC. Il s’agit du profil de collection d’événements GC le moins détaillé avec l’impact le plus faible sur les performances de l’application cible. Cette commande est similaire à la commande PerfView.exe /GCCollectOnly collect dans PerfView.

  • perfcollect collect -gconly

Collectez des événements de collection GC plus détaillés avec des événements JIT, Chargeur et Exception. Cela demande davantage d’événements détaillés (tels que les informations d’allocation et les informations de jointure GC) et aura plus d’impact sur les performances de l’application cible que l’option -gccollectonly. Cette commande est similaire à la commande PerfView.exe /GCOnly collect dans PerfView.

  • perfcollect collect -gcwithheap

Collectez les événements de collection GC les plus détaillés, qui suivent également la survie et les mouvements du segment de mémoire. Cela permet une analyse approfondie du comportement du GC, mais entraîne des coûts de haute performance, car chaque GC peut prendre plus de deux fois plus de temps. Il est recommandé de comprendre l’implication en performances de l’utilisation de cette option de trace lors du traçage dans les environnements de production.