Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article s’applique au ✔️ Kit de développement logiciel (SDK) .NET Core 3.1 et versions ultérieures
Dans ce tutoriel, vous allez apprendre à déboguer un scénario d’utilisation excessive du processeur. En utilisant le référentiel de code source fourni de l'application web ASP.NET Core, vous pouvez provoquer intentionnellement un blocage. Le point de terminaison cesse de répondre et subit une accumulation de threads. Vous découvrirez comment utiliser différents outils pour diagnostiquer ce scénario avec plusieurs éléments clés de données de diagnostic.
Dans ce didacticiel, vous allez :
- Examiner l’utilisation élevée du processeur
- Déterminer l’utilisation du processeur avec dotnet-counters
- Utiliser dotnet-trace pour la génération de trace
- Performances de profil dans PerfView
- Diagnostiquer et résoudre une utilisation excessive du processeur
Prerequisites
Le tutoriel utilise :
- Sdk .NET Core 3.1 ou version ultérieure.
- Exemple de cible de débogage pour déclencher le scénario.
- dotnet-trace pour répertorier les processus et générer un profil.
- dotnet-counters pour surveiller l’utilisation du processeur.
Compteurs d’UC
Avant d’essayer ce tutoriel, installez la dernière version de dotnet-counters :
dotnet tool install --global dotnet-counters
Si votre application exécute une version de .NET antérieure à .NET 9, l’interface utilisateur de sortie des compteurs dotnet est légèrement différente ; pour plus d’informations, consultez dotnet-counters .
Avant de tenter de collecter des données de diagnostic, vous devez observer une forte utilisation du processeur. Exécutez l’exemple d’application à l’aide de la commande suivante à partir du répertoire racine du projet.
dotnet run
Pour vérifier l’utilisation actuelle du processeur, utilisez la commande de l’outil dotnet-counters :
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
La sortie doit être similaire à ce qui suit :
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.109 0
user 0.453 0
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
En mettant l’accent sur les valeurs de dotnet.process.cpu.time, celles-ci nous indiquent combien de secondes l’UC a été active pendant la période d’actualisation (actuellement définie sur la valeur par défaut de 1 s). Avec l’application web en cours d’exécution, immédiatement après le démarrage, l’UC n'est pas du tout sollicitée et ces deltas sont tous deux 0. Accédez à l’itinéraire api/diagscenario/highcpu avec 60000 comme paramètre d’itinéraire :
https://localhost:5001/api/diagscenario/highcpu/60000
À présent, réexécutez la commande dotnet-counters .
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
Vous devriez voir une augmentation de l’utilisation du processeur, comme indiqué ci-dessous (en fonction de l’ordinateur hôte, attendez-vous à une utilisation variable de l’UC) :
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.344 0.013
user 14.203 0.963
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
Pendant toute la durée de la requête, l'utilisation du processeur se maintiendra autour du niveau élevé.
Conseil / Astuce
Pour visualiser une utilisation encore plus élevée du processeur, vous pouvez exercer ce point de terminaison dans plusieurs onglets de navigateur simultanément.
À ce stade, vous pouvez affirmer sans risque que le processeur fonctionne plus rapidement que prévu. Identifier les effets d’un problème est essentiel pour trouver la cause. Nous allons utiliser l’effet d’une consommation élevée du processeur en plus des outils de diagnostic pour trouver la cause du problème.
Analyser le processeur élevé avec Profiler
Lors de l’analyse d’une application avec une utilisation élevée du processeur, utilisez un profileur pour comprendre ce que fait le code.
dotnet-trace collect fonctionne sur tous les systèmes d’exploitation, mais les biais de point sûr et les piles d’appels managées le limitent à des informations plus générales qu’un profileur prenant en charge le noyau comme ETW pour Windows ou perf pour Linux. Selon votre système d’exploitation et votre version .NET, des fonctionnalités de profilage améliorées peuvent être disponibles : consultez les onglets spécifiques à la plateforme qui suivent pour obtenir des instructions détaillées.
Utiliser dotnet-trace collect-linux (.NET 10+)
Sur .NET 10 et versions ultérieures, dotnet-trace collect-linux il s’agit de l’approche de profilage recommandée sur Linux. Il combine EventPipe avec des perf_events au niveau du système d’exploitation pour produire une seule trace unifiée qui inclut à la fois des piles d’appels managées et natives, sans nécessiter de redémarrage de processus. Cela nécessite des droits root et le noyau Linux 6.4+ avec CONFIG_USER_EVENTS=y. Consultez les conditions préalables à collect-linux pour connaître les exigences complètes.
Vérifiez que l’exemple de cible de débogage est configuré pour cibler .NET 10 ou une version ultérieure, puis exécutez-le et effectuez à nouveau l’exercice du point de terminaison processeur élevé (https://localhost:5001/api/diagscenario/highcpu/60000). Pendant l'exécution de la requête d'une minute, exécutez dotnet-trace collect-linux pour capturer une trace au niveau de la machine :
sudo dotnet-trace collect-linux
Laissez-le s’exécuter pendant environ 20 à 30 secondes, puis appuyez sur Ctrl+C ou Entrée pour arrêter la collection. Le résultat est un .nettrace fichier qui inclut des piles d’appels managées et natives.
Ouvrez .nettrace avec PerfView et utilisez la vue Piles du processeur pour identifier les méthodes qui consomment le plus de temps CPU.
Pour obtenir plus d’informations sur la résolution des symboles d’exécution natifs dans la trace, consultez Obtenir des symboles pour les cadres d'exécution natives.
Utilisez perf.
L’outil perf peut également être utilisé pour générer des profils d’application .NET Core. Quittez l’instance précédente de l’échantillon de cible de débogage.
Définissez la DOTNET_PerfMapEnabled variable d’environnement pour que l’application .NET crée un map fichier dans le /tmp répertoire. Ce map fichier est utilisé par perf pour mapper les adresses CPU aux fonctions générées par JIT, par leur nom. Pour plus d’informations, consultez Exporter les cartes perf et les vidages jit.
Exécutez l’exemple de cible de débogage dans la même session de terminal.
export DOTNET_PerfMapEnabled=1
dotnet run
Utilisez à nouveau le point de terminaison de l'API de haute utilisation CPU (https://localhost:5001/api/diagscenario/highcpu/60000). Pendant qu’elle s’exécute dans la requête de 1 minute, exécutez la commande avec votre perf ID de processus :
sudo perf record -p 2266 -g
La perf commande démarre le processus de collecte des performances. Laissez-le s’exécuter pendant environ 20 à 30 secondes, puis appuyez sur Ctrl+C pour quitter le processus de collecte. Vous pouvez utiliser la même perf commande pour afficher la sortie de la trace.
sudo perf report -f
Vous pouvez également générer un graphe de flamme à l’aide des commandes suivantes :
git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
Cette commande génère un flamegraph.svg que vous pouvez voir dans le navigateur pour examiner le problème de performance.
Analyse de données processeur élevées avec Visual Studio
Tous les fichiers *.nettrace peuvent être analysés dans Visual Studio. Pour analyser un fichier *.nettrace Linux dans Visual Studio, transférez le fichier *.nettrace, en plus des autres documents nécessaires, vers une machine Windows, puis ouvrez le fichier *.nettrace dans Visual Studio. Pour plus d’informations, consultez Analyser les données d’utilisation du processeur.
Voir aussi
- dotnet-trace pour répertorier les processus
- dotnet-counters pour vérifier l’utilisation de la mémoire managée
- dotnet-dump pour collecter et analyser un fichier de vidage
- dotnet/diagnostics