Étude de cas : Isoler un problème de performances (C#, Visual Basic, F#)
Utilisez les outils de profilage pour examiner les problèmes de performances et isoler les zones de problèmes. Cette étude de cas utilise un exemple d’application avec des problèmes de performances pour montrer comment utiliser des outils de profilage pour améliorer l’efficacité. Si vous souhaitez comparer les outils de profilage, consultez Quel outil dois-je choisir ?
Cette étude de cas aborde ces sujets :
- Comment utiliser les outils de profilage Visual Studio pour analyser les performances des applications.
- Comment interpréter les données fournies par ces outils pour identifier les goulots d’étranglement des performances.
- Comment appliquer des stratégies pratiques pour optimiser le code, en mettant l’accent sur les compteurs .NET, les nombres d’appels et les données de minutage.
Suivez et appliquez ces techniques à vos propres applications pour les rendre plus efficaces et rentables.
Isoler une étude de cas sur un problème de performance
L’exemple d’application dans cette étude de cas est une application ASP.NET qui exécute des requêtes sur une base de données simulée. L'exemple est basé sur l'échantillon Diagnostics.
Le principal problème de performances avec l’exemple d’application réside dans des modèles de codage inefficaces. L’application a un goulot d’étranglement des performances qui a un impact significatif sur son efficacité. Le problème inclut les symptômes suivants :
Faible utilisation de l'UC: L’application indique une faible utilisation de l’UC, ce qui montre que l’UC n’est pas le goulot d’étranglement.
Nombre élevé de threads du ThreadPool : le nombre de threads est relativement élevé et augmente régulièrement, ce qui suggère un épuisement du pool de threads.
réponse lente de l’application : l’application répond lentement en raison du manque de threads disponibles pour traiter de nouveaux éléments de travail.
L’étude de cas vise à résoudre ces problèmes en utilisant les outils de profilage de Visual Studio pour analyser les performances de l’application. En comprenant où et comment les performances de l’application peuvent être améliorées, les développeurs peuvent implémenter des optimisations pour rendre le code plus rapide et plus efficace. L’objectif ultime est d’améliorer les performances globales de l’application, ce qui rend l’exécution plus efficace et rentable.
Défi
La résolution des problèmes de performances dans l’exemple d’application .NET présente plusieurs défis. Ces défis découlent de la complexité du diagnostic des goulots d’étranglement des performances. Les principaux défis liés à la résolution des problèmes décrits sont les suivants :
Diagnostiquer les goulots d’étranglement des performances : l’un des principaux défis consiste à identifier avec précision les causes racines des problèmes de performance. Une faible utilisation du processeur combinée à des performances lentes peut avoir plusieurs facteurs de contribution. Les développeurs doivent utiliser efficacement des outils de profilage pour diagnostiquer ces problèmes, ce qui nécessite une compréhension de la façon dont ces outils fonctionnent et comment interpréter leur sortie.
contraintes de connaissances et de ressources: Teams peut faire face à des contraintes liées aux connaissances, à l’expertise et aux ressources. Le profilage et l’optimisation d’une application nécessitent des compétences et une expérience spécifiques, et toutes les équipes n’ont pas nécessairement un accès immédiat à ces ressources.
La résolution de ces défis nécessite une approche stratégique qui combine une utilisation efficace des outils de profilage, des connaissances techniques et une planification et des tests minutieux. L’étude de cas vise à guider les développeurs dans ce processus, en fournissant des stratégies et des insights pour surmonter ces défis et améliorer les performances de l’application.
Stratégie
Voici une vue générale de l’approche dans cette étude de cas :
- Nous commençons l’examen en observant les métriques de compteur .NET lors de la collecte des données de performance. Comme l’outil Utilisation du processeur, l’outil Compteurs .NET de Visual Studio constitue également un bon point de départ pour une investigation des performances.
- Ensuite, pour obtenir des insights supplémentaires pour isoler les problèmes ou améliorer les performances, envisagez de collecter une trace à l’aide de l’un des autres outils de profilage. Par exemple, examinez le nombre d’appels et les données de chronométrage en utilisant l’outil Instrumentation.
La collecte de données nécessite les tâches suivantes :
- Paramètre de l’application en mode build de mise en production.
- Sélectionnez l’outil Compteurs .NET dans le Profileur de Performance (Alt+F2). (Les étapes ultérieures comprennent l’outil d’instrumentation.)
- À partir du Profileur de performances, démarrez l’application et collectez une trace.
Vérifier les compteurs de performances
Lors de l’exécution de l’application, nous observons les compteurs dans l’outil Compteurs .NET. Pour les enquêtes initiales, gardez un œil sur quelques indicateurs clés, notamment :
CPU Usage
. Regardez ce compteur pour déterminer si un problème de performances se produit avec une utilisation élevée ou faible du processeur. Il peut s’agir d’un indice sur des types spécifiques de problèmes de performances. Par exemple:- Avec une utilisation élevée du processeur, utilisez l’outil Utilisation du processeur pour identifier les zones où nous pouvons optimiser le code. Pour obtenir un didacticiel sur ce sujet, consultez Étude de cas : Guide du débutant pour optimiser le code.
- Avec une faible utilisation du processeur, utilisez l’outil Instrumentation pour identifier les nombres d’appels et le temps de fonction moyen en fonction de l’heure du mur. Cela peut aider à identifier les problèmes tels que la contention ou l’épuisement du pool de threads.
Allocation Rate
. Pour une application web qui répond aux demandes, le taux doit être assez stable.GC Heap Size
. Surveillez ce compteur pour voir si l'utilisation de la mémoire augmente continuellement et présente des fuites potentielles. S’il semble élevé, utilisez l’un des outils d’utilisation de la mémoire.Threadpool Thread Count
. Pour une application web qui répond aux demandes, regardez ce compteur pour voir si le nombre de threads est stable ou augmente à un rythme stable.
Voici un exemple montrant comment la CPU Usage
est faible, tandis que la ThreadPool Thread Count
est relativement élevée.
Une augmentation constante du nombre de threads avec une faible utilisation du processeur peut être un indicateur de la faim du pool de threads. Le pool de threads est forcé de continuer à créer de nouveaux threads. L'épuisement du pool de threads se produit lorsque le pool n’a pas de threads disponibles pour traiter de nouvelles tâches, ce qui entraîne souvent une réponse lente des applications.
Sur la base de la faible utilisation du processeur et du nombre relativement élevé de threads, et en travaillant sur la théorie d'un cas possible d’épuisement du pool de threads, passez à l’utilisation de l’outil Instrumentation.
Examiner les nombres d’appels et les données de minutage
Examinons une trace de l’outil Instrumentation pour voir si nous pouvons essayer d’en savoir plus sur ce qui se passe avec les threads.
Après avoir collecté une trace avec l’outil Instrumentation et en la chargeant dans Visual Studio, nous vérifions d’abord la page de rapport initiale .diagsession qui affiche les données résumées. Dans la trace collectée, nous utilisons le lien Ouvrir les détails dans le rapport, puis nous sélectionnons Graphique en flamme.
La visualisation de Flame Graph nous montre que la fonction QueryCustomerDB
(illustrée en jaune) est responsable d’une partie importante du temps d’exécution de l’application.
Faites un clic droit sur la fonction QueryCustomerDB
et choisissez Affichage dans l’arborescence des appels.
Le chemin du code avec une utilisation maximale du processeur dans l’application est appelé chemin chaud. L’icône de flamme du chemin d'accès chaud () peut aider à identifier rapidement les problèmes de performances pouvant être améliorés.
Dans la vue Arborescence des appels, vous pouvez voir que le chemin chaud inclut la fonction QueryCustomerDB
, qui pointe vers un problème potentiel de performances.
Par rapport au temps passé dans d’autres fonctions, les valeurs Self et Avg Self pour la fonction QueryCustomerDB
sont très élevées. Contrairement à Total et Moyenne Totale, les valeurs Self excluent le temps passé dans d’autres fonctions, ce qui en fait un bon endroit pour rechercher le goulot d’étranglement des performances.
Conseil
Si les valeurs de Self étaient relativement basses au lieu d’être élevées, vous aimeriez probablement examiner les requêtes réelles appelées par la fonction QueryCustomerDB
.
Double-cliquez sur la fonction QueryCustomerDB
pour afficher le code source de la fonction.
public ActionResult<string> QueryCustomerDB()
{
Customer c = QueryCustomerFromDbAsync("Dana").Result;
return "success:taskwait";
}
Nous faisons un peu de recherche. Nous pouvons également gagner du temps et laisser Copilot faire la recherche pour nous.
Si nous utilisons Copilot, sélectionnez Demander à Copilot dans le menu contextuel et tapez la question suivante :
Can you identify a performance issue in the QueryCustomerDB method?
Conseil
Vous pouvez utiliser des commandes obliques telles que /optimize pour vous aider à poser de bonnes questions à Copilot.
Copilot nous indique que ce code appelle une API asynchrone sans utiliser await. Il s'agit du modèle de code synchrone sur asynchrone, qui est une cause courante d’épuisement du pool de threads, pouvant bloquer les threads.
Pour résoudre ce problème, utilisez await. Dans cet exemple, Copilot fournit la suggestion de code suivante, ainsi que l’explication.
public async Task<ActionResult<string>> QueryCustomerDB()
{
Customer c = await QueryCustomerFromDbAsync("Dana");
return "success:taskwait";
}
Si vous constatez des problèmes de performances liés aux requêtes de base de données, vous pouvez utiliser l’outil de base de données pour déterminer si certains appels sont plus lents. Ces données peuvent indiquer une opportunité d’optimiser les requêtes. Pour obtenir un didacticiel montrant comment utiliser l’outil De base de données pour examiner un problème de performances, consultez Étude de cas : Guide du débutant pour optimiser le code. L’outil Base de données prend en charge .NET Core avec ADO.NET ou Entity Framework Core.
Pour obtenir des visualisations dans Visual Studio pour un comportement de thread individuel, vous pouvez utiliser la fenêtre Piles parallèles lors du débogage. Cette fenêtre affiche les threads individuels ainsi que des informations sur les threads en attente, les threads sur lesquels ils attendent et les interblocages.
Pour plus d’informations sur l’épuisement du pool de threads, consultez Détection de l'épuisement du pool de threads.
Étapes suivantes
Les articles et billets de blog suivants fournissent plus d’informations pour vous aider à apprendre à utiliser efficacement les outils de performances de Visual Studio.
- Étude de cas : guide du débutant pour optimiser le code
- Étude de cas : double performance en moins de 30 minutes
- Améliorer les performances de Visual Studio avec le nouvel outil d’instrumentation