Analyser les performances en utilisant le profilage du processeur dans le Profileur de performances (C#, Visual Basic, C++, F#)
Une bonne façon de commencer à analyser les problèmes de performances dans votre application est de comprendre son utilisation du processeur à l’aide d’un outil de profilage CPU. L’outil de performances Utilisation du processeur de Visual Studio montre le temps et le pourcentage de calcul actif du processeur consacré à l’exécution de code en C++, C#/Visual Basic.
L’outil Utilisation du processeur peut vous aider à :
Diagnostiquer un ralentissement ou un blocage de processus dans la base de code de votre équipe. L’outil peut vous aider à diagnostiquer le problème lié au code de production de votre équipe. Il fournit des insights automatiques et différentes vues de vos données pour vous permettre d’analyser et de diagnostiquer les problèmes de performances.
Identifier des problèmes de performances dans les scénarios DevOps Par exemple, l’outil peut vous aider quand un client signale que certaines requêtes ou commandes ne sont pas envoyées au site web de vente au détail pendant la saison haute. Souvent, les problèmes apparaissent en phase de production et il est difficile de déboguer à ce moment-là, mais cet outil peut vous aider à capturer suffisamment d’informations et de preuves concernant le problème. Après la collecte d’un fichier de trace, l’analyse peut vous aider à comprendre rapidement les causes potentielles et donner des suggestions dans le contexte de votre code pour vous permettre d’effectuer les étapes suivantes afin de corriger le problème.
Rechercher s’il y a une utilisation élevée du processeur Si votre problème de latence ne concerne pas une requête d’API, vous pouvez rechercher une utilisation élevée du processeur et d’autres problèmes connexes avec l’outil Utilisation du processeur. L’outil Utilisation du processeur peut vous aider à identifier les goulots d’étranglement pour vous permettre de déterminer de façon plus précise l’élément à optimiser.
L’outil Utilisation de l’UC est utile à la fois pour les sessions de suivi locales et la production. Vous pouvez exécuter l’outil Utilisation du processeur en utilisant le raccourci clavier Alt+F2, puis en choisissant Utilisation du processeur, ou en ouvrant une trace déjà collectée en utilisant un outil comme dotnet-trace ou dotnet-monitor. (Pour le code de production .NET, c’est probablement la façon dont vous collectez les traces.)
Vous pouvez exécuter l’outil Utilisation du processeur sur un projet Visual Studio ouvert ou sur une application du Microsoft Store installée, ou bien l’attacher à une application ou un processus en cours d’exécution. Vous pouvez exécuter l’outil Utilisation du processeur sur des builds de version ou de débogage. Pour plus d’informations, consultez Exécuter des outils de profilage sur des builds de version ou de débogage.
Les instructions suivantes indiquent comment utiliser l’outil Utilisation du processeur sans le débogueur, en utilisant le Profileur de performances de Visual Studio. Les exemples utilisent une build de version sur une machine locale. Les builds de version offrent la meilleure vision sur les performances réelles de l’application. Pour obtenir un tutoriel qui montre comment améliorer les performances en utilisant l’outil Utilisation du processeur, consultez Étude de cas : Guide du débutant pour l’optimisation du code.
En règle générale, c’est la machine locale qui réplique le mieux l’exécution des applications installées. Pour collecter des données depuis un appareil distant, exécutez l’application directement sur l’appareil, et non pas via une connexion Bureau à distance.
Collecter les données d’utilisation du processeur
Dans le projet Visual Studio, définissez la configuration de la solution sur Release et sélectionnez Débogueur Windows local (ou Machine locale) comme cible de déploiement.
Sélectionnez Déboguer>Profileur de performances.
Sous Outils disponibles, sélectionnez Utilisation de l’UC, puis Démarrer.
Si vous activez l’option Démarrer avec la collecte suspendue avant de démarrer le profileur, les données ne sont pas collectées tant que vous ne sélectionnez pas le bouton Enregistrer dans la vue de session de diagnostic.
Remarque
Pour plus d’informations sur la façon de rendre l’outil plus efficace, consultez Optimisation des paramètres du Profileur.
Une fois que l’application a démarré, la session de diagnostic commence et affiche les données d’utilisation du processeur. Quand vous avez terminé la collecte des données, sélectionnez Arrêter la collecte.
L’outil Utilisation du processeur analyse les données et affiche le rapport. Si vous rencontrez des problèmes lors de la collecte ou de l’affichage des données, consultez Résoudre les erreurs de profilage et corriger les problèmes.
Utilisez la liste déroulante Filtre pour sélectionner ou désélectionner des threads à afficher, et utilisez la zone Rechercher pour rechercher un nœud ou un thread spécifique.
Colonnes de données de l’utilisation du processeur
Nom | Description |
---|---|
Temps processeur total [unité, %] | ![]() Les millisecondes de temps de calcul d’UC et le pourcentage d’UC utilisé par les appels à la fonction, et les fonctions appelées par la fonction, dans l’intervalle de temps sélectionné. Ceci est différent du graphique chronologique d'utilisation du processeur, qui compare l'activité totale du processeur dans un intervalle de temps à la capacité totale disponible du processeur. |
Temps UC exclusif [unité, %] | ![]() Le temps de calcul du processeur en millisecondes et le pourcentage de CPU utilisé par les appels à la fonction dans l’intervalle de temps sélectionné, qui exclut les fonctions appelées par la fonction. |
Module | Dans certaines vues, la colonne Module s’affiche et indique le nom du module contenant la fonction. |
Analyser les aperçus sur le processeur
Si des insights apparaissent dans la section Insights principaux, utilisez le lien fourni pour obtenir plus d’informations sur le problème identifié. En outre, si vous utilisez Copilot, le bouton Demander à Copilot ouvre la fenêtre de conversation Copilot, Copilot fournissant alors des suggestions en fonction de votre code et des problèmes identifiés.
Pour plus d’informations, consultez Insights de l’UC.
Analyser l’utilisation du processeur
Pour analyser l’utilisation du processeur, cliquez sur Ouvrir les détails ou cliquez sur une des fonctions principales pour ouvrir la vue Fonctions.
Le rapport fournit différentes vues des données de diagnostic :
Afficher | Description |
---|---|
Appelant/appelé | Vue détaillée du temps processeur d’une fonction spécifique, de la ou des fonctions qui l’ont appelée et de la ou des fonctions qu’elle appelle. Les données de performances sont agrégées pour la période de collecte de données. Vous pouvez sélectionner des fonctions appelantes et des fonctions appelées pour parcourir le chemin d’appel. |
Arborescence des appels | Vue hiérarchique du chemin des appels de fonction. Permet d’identifier les chemins d’appel qui prennent le plus de temps processeur (chemin d’accès chaud). |
Modules | Vue du temps processeur passé dans des modules individuels, agrégés au cours de la période de collecte de données. Permet d’identifier les modules susceptibles d’être des goulots d’étranglement des performances en raison d’une combinaison de nombres d’appels élevés et/ou de problèmes de performances. |
Fonctions | Vue du temps processeur passé dans des fonctions individuelles, agrégées au cours de la période de collecte de données. Permet d’identifier les fonctions susceptibles d’être des goulots d’étranglement des performances en raison d’une combinaison de nombres d’appels élevés et/ou de problèmes de performances. |
Graphique en flamme | Vue hiérarchique du chemin d’appel de la fonction dans une visualisation de graphique en flamme. Permet d’identifier les chemins d’appel qui prennent le plus de temps processeur (chemin d’accès chaud). |
Pour analyser le rapport, cliquez sur Créer un rapport détaillé.
Le rapport fournit différentes vues des données de diagnostic :
- Appelant/appelé
- Arborescence des appels
Dans toutes les vues, à l’exception de Appelant/appelé, le rapport de diagnostic est trié par Total de processeur, du plus élevé au plus faible. Changez l’ordre de tri ou la colonne de tri en sélectionnant les en-têtes de colonne. Vous pouvez double-cliquer sur une fonction qui vous intéresse : vous verrez la source de la fonction et là où du temps est passé dans cette fonction. Le tableau contient des colonnes avec des données comme le temps passé dans la fonction, y compris les fonctions appelées (Total processeur), et une deuxième colonne qui montre le temps passé dans une fonction, à l’exclusion des fonctions appelées (Temps UC exclusif).
Ces données peuvent vous aider à évaluer si la fonction elle-même est un goulot d’étranglement. Déterminez la quantité de données affichées par la méthode pour voir si le code ou les bibliothèques d'exécution tiers sont responsables de la lenteur de vos points de terminaison ou de leur forte consommation de ressources.
Pour plus d’informations sur l’utilisation du Flame Graph, consultez Identifier les chemins critiques avec le Flame Graph.
Arborescence des appels de l’utilisation du processeur
Pour voir l’arborescence des appels, sélectionnez le nœud parent dans le rapport. Par défaut, la page Utilisation de l’UC s’ouvre sur la vue Appelant/appelé. Dans la liste déroulante Vue actuelle, sélectionnez Arborescence des appels.
Vous pouvez cliquer sur les boutons Développer le chemin chaud et Afficher le chemin chaud pour voir les appels de fonction qui utilisent le pourcentage le plus élevé du processeur dans la vue de l’arborescence des appels.
Structure de l’arborescence des appels
Image | Description |
---|---|
![]() |
Le nœud de plus haut niveau dans l’arborescence des appels de l’utilisation du processeur, représentant l’application. |
![]() |
Dans la plupart des applications, quand l’option Afficher le code externe est désactivée, le nœud de second niveau est un nœud [Code externe]. Le nœud contient le code du système et du framework qui démarre et arrête l’application, dessine l’interface utilisateur, contrôle la planification des threads et fournit d’autres services de bas niveau à l’application. |
![]() |
Les enfants du nœud de deuxième niveau sont les méthodes du code utilisateur et des routines asynchrones appelées ou créées par le code du système et du framework de deuxième niveau. |
![]() |
Les nœuds enfants d’une méthode ont des données seulement pour les appels de la méthode parente. Lorsque Afficher le code externe est désactivé, les méthodes de l'application peuvent également contenir un nœud [Code externe]. |
Code externe
Les fonctions du système et du framework qui sont exécutées par votre code sont appelées code externe. Les fonctions du code externe démarrent et arrêtent l’application, dessinent l’interface utilisateur, contrôlent les threads et fournissent d’autres services de bas niveau à l’application. Dans la plupart des cas, le code externe ne vous intéresse pas ; par conséquent, l’arborescence des appels de l’utilisation du processeur regroupe les fonctions externes d’une méthode utilisateur dans un seul nœud [Appel externe].
Pour afficher les chemins d’appel du code externe, dans la page récapitulative du rapport principal (volet droit), désélectionnez Afficher uniquement mon code de la liste déroulante Paramètres , puis sélectionnez Appliquer. (La liste déroulante des paramètres est disponible uniquement sur la page récapitulative du rapport principal, et non sur les vues détaillées.)
Les fonctions du système et du framework qui sont exécutées par votre code sont appelées code externe. Les fonctions de code externe démarrent et arrêtent l’application, dessinent l’interface utilisateur, contrôlent les threads et fournissent d’autres services de bas niveau à l’application. Dans la plupart des cas, le code externe ne vous intéresse pas ; par conséquent, l’arborescence des appels de l’utilisation du processeur regroupe les fonctions externes d’une méthode utilisateur dans un seul nœud [Code externe].
Pour voir les chemins d’appel du code externe, sélectionnez Afficher le code externe dans la liste déroulante Filtrer de la page principale des rapports de diagnostic (volet droit), puis sélectionnez Appliquer. La vue Arborescence des appels de la page Utilisation du processeur développe alors les appels de code externe. (La liste déroulante Filtrer est disponible sur la page principale des diagnostics, et non sur les vues détaillées.)
Quand vous désactivez Afficher uniquement mon code, la vue Arborescence des appels de la page Utilisation du processeur développe les appels de code externe.
De nombreuses chaînes d’appels de code externe sont imbriquées en profondeur ; par conséquent, la largeur de la chaîne peut dépasser la largeur d’affichage de la colonne Nom de la fonction. Les noms des fonctions apparaissent ensuite comme illustré dans l’image suivante.
De nombreuses chaînes d’appels de code externe sont imbriquées en profondeur ; par conséquent, la largeur de la chaîne peut dépasser la largeur d’affichage de la colonne Nom de la fonction. Les noms des fonctions apparaissent alors sous la forme ....
Pour rechercher un nom de fonction, utilisez la zone de recherche. Placez le curseur sur la ligne sélectionnée ou utilisez la barre de défilement horizontale pour voir les données.
Fonctions asynchrones dans l’arborescence des appels de l’utilisation du processeur
Quand le compilateur rencontre une méthode asynchrone, il crée une classe masquée pour contrôler l’exécution de la méthode. Conceptuellement, la classe est une machine à états. Elle a des fonctions générées par le compilateur qui appellent de façon asynchrone les méthodes d’origine ainsi que les rappels, le planificateur et les itérateurs nécessaires pour les exécuter. Quand une méthode parente appelle la méthode d’origine, le compilateur supprime la méthode du contexte d’exécution du parent et exécute les méthodes de la classe masquée dans le contexte du code du système et du framework qui contrôle l’exécution de l’application. Les méthodes asynchrones sont souvent, mais pas toujours, exécutées sur un ou plusieurs threads différents. Ce code est affiché dans l’arborescence des appels de l’Utilisation du processeur en tant qu’enfants du nœud [Code externe] situé immédiatement sous le nœud de plus haut niveau de l’arborescence.
Dans l’exemple suivant, les deux premiers nœuds sous [Code externe] sont les méthodes générées par le compilateur de la classe de la machine à états. Le troisième nœud est l’appel à la méthode d’origine.
Développez les méthodes générées pour voir ce qui se passe :
MainPage::GetMaxNumberAsyncButton_Click
gère simplement la liste des valeurs de la tâche, calcule le nombre maximal de résultats et affiche la sortie.MainPage+<GetMaxNumberAsyncButton_Click>d__3::MoveNext
vous montre l’activité requise pour planifier et lancer les 48 tâches qui encapsulent l’appel àGetNumberAsync
.MainPage::<GetNumberAsync>b__b
montre l’activité des tâches qui appellentGetNumber
.
Collecter le nombre d’appels (.NET)
Si vous voulez voir le nombre d’appels dans la vue Fonctions, vous pouvez activer le paramètre avant de démarrer le profileur. Ce paramètre est pris en charge pour des types de projet .NET et nécessite le lancement du processus sous le profileur. Le scénario d’attachement n’est pas pris en charge.
Sélectionnez l'icône Paramètres pour l'utilisation du processeur dans le Profileur de performances.
Activez l’option Collecter le nombre d’appels (.NET uniquement).
Collecter les données d’utilisation du processeur
Ouvrez la vue Fonctions, puis assurez-vous que la colonne Nombre d'appels est définie comme visible.
Si vous ne voyez pas la colonne, cliquez avec le bouton de droite sur un en-tête de colonne pour choisir les colonnes visibles.