Partager via


Cet article a fait l'objet d'une traduction automatique.

Performances des threads

Profilage de simultanéité des contentions de ressources dans Visual Studio 2010

Maxim Goldin

Comme les processeurs multicoeur deviennent de plus en plus répandus, les développeurs de logiciels créent des applications multithread qui tirent parti de la capacité de traitement supplémentaire pour obtenir de meilleures performances. À l'aide de la puissance de threads en parallèle, vous pouvez fractionner le travail total en tâches distinctes et exécuter ces tâches en parallèle.

Threads, cependant, doivent souvent communiquer entre eux pour terminer une tâche et parfois besoin de synchroniser leur comportement si un accès à un algorithme ou données l'exige. Par exemple, un accès en écriture simultanément aux mêmes données doit être accordé aux threads de façon à éviter la corruption des données qui s'excluent mutuellement.

Synchronisation s'effectue souvent via l'utilisation d'objets de synchronisation partagé, où le thread acquisition de l'objet est accordé l'accès partagé ou exclusif pour le code sensible ou des données. Lors de l'accès n'est plus nécessaire, le thread abandonne la propriété et l'autre thread peut tenter d'acquérir l'accès. Selon le type de synchronisation utilisé, nombre de demandes simultanées pour la propriété peut permettre à plusieurs threads accéder aux ressources partagées en même temps, ou parmi les threads sont peut-être bloqués jusqu'à ce que l'objet est libéré de l'acquisition précédente. Exemples 
include sections critiques en C/C++ qui utilisent les routines d'accès EnterCriticalSection et LeaveCriticalSection, la fonction WaitForSingleObject en C/C++ et l'instruction lock et la classe Monitor en c#.

Le choix du mécanisme de synchronisation doit être effectué avec précaution, car une mauvaise synchronisation entre les threads peut réduire au lieu d'améliorer les gains de performance sont l'objectif de multithreading. Par conséquent, il est plus en plus important être en mesure de détecter des situations où les threads sont bloqués en raison de conflits de verrouillage pas progresser.

Les outils de performances de Visual Studio 2010 incluent une nouvelle méthode de profilage, profilage de contention des ressources, qui vous permet de détecter les conflits de concurrence d'accès entre les threads. Vous trouverez un bon premier aperçu de cette fonctionnalité dans un billet de blog Wintellect ’ John Robbins à wintellect.com/CS/blogs/jrobbins/archive/2009/10/19/vs-2010-beta-2-concurrency-resource-profiling-in-depth-first-look.aspx de .

Dans cet article, j'ai guident tout au long d'une enquête de contention de profilage et expliquez les données peuvent être collectées à l'aide de l'environnement IDE de Visual Studio 2010 et les outils de ligne de commande. Je vous montrerai également comment vous pouvez analyser les données dans Visual Studio 2010, et vous verrez comment faire pour déplacer à partir de la vue d'analyse d'une à l'autre lors de la conduite de votre enquête de contention. Puis je corrige le code et de comparer les résultats de l'application modifiée avec les résultats de profilage d'origine afin de valider que le correctif réduit le nombre de conflits de profilage.

Démarrer avec le problème.

Par exemple, je vais utiliser la même application de multiplication de matrice Hazim Shafi utilisé dans son billet de blog “ performance motif 1 : Identification de contention de verrouillage ” (blogs.msdn.com/hshafi/archive/2009/06/19/performance-pattern-1-identifying-lock-contention.aspx ). L'exemple de code est écrit en C++, mais les concepts que j'aborderai sont applique également à du code managé.

L'application de multiplication de matrice exemple utilise plusieurs threads pour multiplier deux matrices. Chaque thread Obtient une partie du travail et exécute l'extrait de code suivant :

for (i = myid*PerProcessorChunk; 
     i < (myid+1)*PerProcessorChunk; 
     i++) {
  EnterCriticalSection(&mmlock);
  for (j=0; j<SIZE; j++) {
    for (k=0; k<SIZE; k++) {
      C[i][j] += A[i][k]*B[k][j];
    }
  }
  LeaveCriticalSection(&mmlock);
}

Chaque thread possède son propre ID (myid) et est chargé du calcul du nombre de lignes (une ou plusieurs) dans la matrice résultante C, à l'aide de matrices A et B en tant qu'entrée. Inspection de la fermeture de code montre que sans véritablement ambigu écriture partage se produit et que chaque thread écrit dans une autre ligne de c. Encore le développeur a décidé de se protéger de l'affectation à la matrice avec une section critique. Je remercie le développeur pour ce faire, tel qu'il donne une bonne occasion de montrer les nouveaux outils de performances de Visual Studio 2010 pour trouver facilement la synchronisation redondante.

Collecte de données de profilage

En supposant que vous avez un projet Visual Studio avec le code illustré précédemment (bien qu'il n'est pas obligatoire — vous pouvez attacher le profileur à n'importe quelle application qui est déjà en cours d'exécution), vous commencez le profilage de conflits en cliquant sur Démarrer l'Assistant Performance dans le menu de l'outil Analyze.

Dans la première page de l'Assistant, illustré à la de figure 1, choisir l'accès concurrentiel et assurez-vous que l'option “ collecte de données de conflit de ressource ” est activée. Remarque Ce d'accès concurrentiel contention de ressources fonctionne sur n'importe quelle version du système d'exploitation Windows le profilage. L'option “ visualiser le comportement d'une application multithread ” nécessite Windows Vista ou Windows 7.

image: Enabling Concurrency Resource Profiling
Figure 1 profil des ressources de l'activation de la simultanéité,

Dans la deuxième page de l'Assistant, assurez-vous que le projet en cours est destiné. Sur la dernière page de l'Assistant, vérifiez que “ lancement lorsque l'Assistant a terminé de profilage ” une option est sélectionnée, puis cliquez sur Terminer. L'application s'exécute dans le Générateur de profils. Lorsque sa sortie, le fichier de données de profil s'affiche dans la fenêtre Explorateur de performances (voir la rubrique de la figure 2 ).

image: Performance Profiling Result File in Performance Explorer
La figure 2 fichier de résultats dans l'Explorateur de performances de profilage des performances

L'état de profilage automatiquement s'ouvre dans Visual Studio et affiche les résultats d'enquête de performances dans la vue Résumé, ce qui est affichée dans les de la figure 3 .

image: Summary View of the Profiling Report
La figure 3 affichage de résumé du rapport profil de

Analyse des données de profilage

Pas toutes les synchronisations provoque une contention de verrouillage. Si un verrou est disponible, une tentative pour devenir un propriétaire du verrou ne bloque pas l'exécution du thread, et pas de conflit se produit. En mode de profilage de conflit de ressources, le profileur de collecte des données uniquement pour les événements de synchronisation provoquant le conflit et ne signale pas les acquisitions de ressources (sans blocage). Si votre application n'entraîne pas les conflits, aucune donnée n'est collectée. Si vous obtenez des données, cela signifie que votre application ait des conflits de verrouillage.

Pour chaque conflit, les rapports du profileur que thread a été bloqué, dans le cas où le conflit s'est produite (ressource et l'appel de pile), lorsque la contention (timestamp) s'est produite et combien de temps (longueur) que le thread a été bloqué tente d'acquérir un verrou, entre une section critique, attendez qu'un seul objet et ainsi de suite.

Lorsque vous ouvrez le fichier, vous verrez tout d'abord la vue Résumé ( de la figure 3 ), avec trois domaines principaux, que vous pouvez utiliser pour les diagnostics brève :

  1. Le graphique de conflits indique le nombre de conflits par seconde sont tracées pour la durée de vie de votre application. Vous pouvez visuellement inspecter des pics de contention ou sélectionnez un intervalle de temps et soit effectuer un zoom avant dans ce ou filtrer les résultats. Le filtrage re-analyzes les données et supprime des données à l'extérieur de l'intervalle sélectionné.
  2. Le tableau traités plus de ressources répertorie les ressources qui a provoqué les plus souvent détectés conflits.
  3. Le tableau plus significatifs de threads répertorie tous les threads ayant le plus grand nombre de conflits. Cette table utilise le nombre de conflits comme critère, et non la longueur des conflits. Par conséquent, vous pouvez avoir un thread est bloqué dans un seul conflit pendant un long moment, mais il ne s'affichent pas dans la vue Résumé. D'autre part, un thread qui a rencontré de nombreux conflits très courtes, avec chaque conflit de bloquer le thread pour seulement très peu de temps, devrait être présenté dans la vue Résumé.

Si une ressource est responsable de la plupart des conflits s'affiche, vérifiez que cette ressource de manière plus détaillée. Si vous observez un thread qui rencontre un grand nombre de conflits, que vous ne vous attendiez pas, vérifiez que les conflits du thread.

Par exemple, dans de la figure 3 , vous pouvez voir que section critique, 1 est responsable de presque tous les conflits (99,90 %) dans cette application. Let’s étudier de plus près cette ressource.

Les noms de ressources et les ID de thread sur la vue Résumé sont des liens hypertexte. En cliquant sur les transferts de section critique 1 vous permet des détails de la ressource Affichez (voir la rubrique de la figure 4 ), où le contexte est défini sur la ressource spécifique — critique section 1.

image: Resource Details View
La figure 4 Affichage des détails de ressources

Détails sur la ressource

La partie supérieure de l'affichage Détails de la ressource affiche un graphique basé sur le moment où chaque ligne horizontale faisant partie d'un thread. Les lignes sont étiquetées par la fonction de racine de thread, à moins que vous nommez le thread géré dans votre code (par exemple, en utilisant la propriété c# System.Threading.Thread.Name). Un bloc de cette ligne représente une contention du thread sur la ressource. La longueur du bloc est la longueur de contention. Blocs de lignes différentes peuvent se chevaucher en temps, ce qui signifie que plusieurs threads bloqués sur la ressource en même temps.

La ligne totale est spéciale. Il n'appartient pas à un thread spécifique, mais contient tous les conflits de tous les threads de cette ressource (il s'agit en fait une projection de contention des blocs de la ligne). Comme vous pouvez le voir, section critique 1 était très occupé, il ne semble pas disposer d'un emplacement sur une ligne total est vide.

Vous pouvez effectuer un zoom sur une partie spécifique du graphique en sélectionnant une tranche de temps à l'aide du bouton gauche de la souris (clic gauche au niveau du point dans le graphique que vous souhaitez démarrer et puis faites glisser le pointeur vers la droite). Il n'y a deux liens de la partie supérieure droite du graphique, zoom réinitialisé et zoom arrière. Zoom réinitialisation restaure la vue du graphique d'origine. Zoom arrière prend que vous arrière étape par étape, un-zooming du graphique la même façon que vous en zoom avant.

Le modèle global de blocs de contention de vous peut entraîner certaines conclusions sur l'exécution de votre application. Par exemple, vous pouvez voir que les conflits de threads différents sont fortement overlapped en temps, ce qui a d'indicateurs au niveau inférieur à la parallélisation optimale. Chaque thread est bloqué sur la ressource beaucoup plus longue qu'elle s'exécute et il s'agit encore d'une autre indication de l'inefficacité de l'application.

Détails de la fonction

La partie inférieure de l'affichage Détails de la ressource est une pile d'appel de contention, aucune donnée n'est affichée jusqu'à ce que vous sélectionnez un conflit spécifique. Lorsque vous sélectionnez un bloc, la pile de correspondante s'affiche dans le volet inférieur. Vous pouvez également pointez sur un bloc de contention dans le graphique sans avoir à cliquer sur celui-ci, et une fenêtre pop-up vous donnera la pile et la longueur de contention.

Comme vous pouvez le voir dans la pile des appels contention, l'une des fonctions d'application d'exemple appelé MatMult est répertorié, afin de savoir qu'il a été la cause de la contention. Pour déterminer quelle ligne de code de la fonction est responsable de la contention, double-cliquez sur le nom de fonction dans le panneau de pile d'appel. Qui vous amène à l'affichage Détails de la fonction, illustré à la de la figure 5 .

image: Function Details View
La figure 5 Affichage des détails de la fonction

Dans cet affichage vous consultez une présentation graphique des fonctions qui ont appelé MatMult, ainsi que les fonctions qui ont été appelées à l'intérieur de celui-ci. La section inférieure de l'affichage montre clairement que EnterCriticalSection(&mmlock) est responsable pour les threads bloqués chaque jour.

Lorsque vous savez quelle ligne de votre code est chargée de conflits, vous pouvez reconsidérer votre décision d'implémenter la synchronisation de cette manière. Est-ce la meilleure façon de protéger votre code ? Est nécessaire de protection du tout ?

Dans l'exemple d'application, à l'aide d'une section critique dans ce code est inutile parce que les threads ne partagent pas d'écritures pour les mêmes lignes de matrice de résultats. Les outils de performance Visual Studio vous permet d'accéder au point où vous pouvez mettre en commentaire l'utilisation de mmlock, considérablement accélérer l'application. Si seulement il s'agissait toujours aussi simple que cela !

Pour obtenir une description plus approfondie du mode Détails d'une fonction, consultez le blog de l'équipe du profileur Visual Studio à blogs.msdn.com/profiler/archive/2010/01/19/vs2010-investigating-a-sample-profiling-report-function-details.aspx de .

Détails des threads

Comme je l'ai mentionné précédemment, le mode Résumé fournit un bon point de départ pour votre investigation. En regardant dans les tables traités plus de ressources et les plus significatifs de threads, vous pouvez décider comment procéder. Si vous trouvez qu'un des threads semble suspect, car vous n'avez pas prévu qu'il soit dans la liste du haut de threads conflictuel, vous pouvez décider de donner un aspect plus proche à la thread.

Cliquez sur l'ID de thread sur la vue Résumé pour afficher les détails des threads afficher (voir la rubrique figure 6-). Bien que cet affichage ressemble à l'affichage Détails de la ressource, il a une signification différente parce qu'il affiche les conflits dans le contexte du thread sélectionné. Chaque ligne horizontale représente une ressource, que le thread a été confronté pour pendant la durée de vie du thread. Dans ce graphique, vous ne verrez pas les blocs de conflits qui se chevauchent dans le temps, cela signifierait que le thread a été bloqué sur plus d'une ressource en même temps.

image: Thread Details View with Selected Contention Block
La figure 6 Afficher les détails avec le bloc de conflit sélectionné de thread,

Notez que WaitForMultipleObjects (dont je suis s'affichent pas ici) est géré séparément et est représenté par une ligne graphique unique pour l'ensemble d'objets. C'est parce que le Générateur de profils traite tous les objets parameter de WaitForMultipleObjects comme une entité unique.

Les manipulations, que vous pouvez faire en mode Détails de la ressource (zoom du graphique et l'extraction, la sélection de conflits spécifiques et affichage de la durée en millisecondes et de la pile appelante) sont applique à la vue d'informations sur le thread ainsi. Double-cliquez sur le nom de fonction dans le panneau de la pile des appels contention pour naviguer vers l'affichage Détails de la fonction de cette fonction.

Dans l'exemple, vous voyez que la thread passe plus de temps bloqué à en cours d'exécution en début de l'exécution, et puis il est bloqué pendant un certain temps sur un ensemble de plusieurs handles. Étant donné que le dernier bloc est provoqué par attendre les autres threads terminer, au plus tôt conflits indiquent l'utilisation des threads non optimale, à l'origine de l'être dans un état bloqué plusieurs dans un état en cours d'exécution du thread.

Résolution par requêtes successives vers le bas le problème.

Comme vous l'avez probablement remarqué, les étiquettes d'axes de graphique sont des liens hypertexte. Cela permet de basculer entre des affichages détaillés des ressources et les threads, définir le contexte nécessaire pour l'affichage chaque fois. Cela peut être utile dans une approche itérative à la recherche et résolution d'un problème. Par exemple, vous pouvez inspecter des ressources R1 bloqué le nombre de threads. Vous pouvez passer les détails de la ressource d'afficher une vue détaillée de la thread T1 et découvrez qu'il a été bloqué non seulement des R1 mais parfois également sur la ressource R2. Vous pouvez ensuite plonger dans les détails de R2 et observer tous les threads qui ont été bloqués par R2. Suivant que vous pouvez cliquer sur l'étiquette de la thread T2 attire votre attention pour vérifier toutes les ressources bloquées T2, et ainsi de suite.

Conflit de données de profilage ne sont pas vous donner une réponse explicite à la question de qui maintient un verrou à un moment donné. Mais étant donné juste d'utilisation de l'objet de synchronisation entre threads et vos connaissances de comportement de l'application, vous pouvez identifier un propriétaire possible de verrou (un thread qui a réussi à l'acquisition de verrou de synchronisation) par glissement de vos données de détails de la ressource vers les détails de la thread et en différé.

Supposons par exemple, dans l'affichage Détails des threads, que vous voyez un thread T est bloqué sur la ressource R au niveau de t de temps. Vous pouvez passer à l'affichage Détails de la ressource de recherche en cliquant sur l'étiquette de R et afficher toutes les threads qui ont été bloqués de R pendant la durée de vie d'application. Au niveau de t de temps, vous verrez un nombre d'entre eux (y compris T) bloqué sur r. Un thread qui n'est pas bloqué au niveau de t de l'heure de R est un détenteur du verrou possible.

Je l'ai indiqué précédemment que la ligne Total du graphique est une projection de tous les blocs de contention. L'étiquette Total est également un lien hypertexte, mais à partir de la vue de détails de la ressource que nécessaire à la contention afficher (voir la rubrique de la figure 7 ), qui est un ensemble d'arborescences d'appel de contention de chaque ressource. Le chemin d'accès rapide de l'arborescence des appels de ressource appropriée est activé pour vous. Cette vue affiche les conflits et les statistiques de temps de blocage pour chaque ressource et pour chaque nœud (fonction) dans l'arborescence des appels ressource. Contrairement aux autres vues, celle-ci regroupe les piles de contention pour l'arborescence des appels ressources, tout comme les autres modes de profilage et donne des statistiques d'exécution de l'ensemble de l'application.

image: Contention View with Hot Path Applied to Critical Section 1
La figure 7 affichage de conflits avec le chemin réactif lettré à la section critique 1

À partir de l'affichage de conflits, vous pouvez revenir à l'affichage Détails de la ressource d'une ressource à l'aide du menu contextuel. Pointez sur une ressource, avec le bouton droit de la souris et sélectionnez Afficher les détails de ressources de conflit. Autres actions intéressantes sont également disponibles dans le menu contextuel. En tant qu'une suggestion générale, explorez les menus contextuels dans les affichages du Générateur de profils, ils peuvent être tout à fait utiles !

Cliquez sur l'étiquette total de la vue Détails des threads pour afficher la vue de processus dans lequel le thread est sélectionné (voir la rubrique de la figure 8 ). Dans cet affichage que vous pouvez voir quand le thread a été démarré par rapport à l'heure de début d'application, lorsqu'elle a été interrompue, la durée pendant laquelle elle s'est déroulée, les conflits rencontrés et la durée pendant laquelle il a été bloqué sur tous les conflits (en millisecondes, en pourcentage de durée de vie du thread).

image: Processes View
La figure 8 vue

Une fois encore, il est possible de revenir en mode Détails de la thread pour n'importe quel thread à l'aide du menu contextuel, sélectionnez un thread d'intérêt, avec le bouton droit et sélectionnez Afficher les détails de contention de threads.

Un autre flux investigation possible consisterait à les afficher directement la vue processus lorsque le fichier est ouvert, les threads pour trier, cliquez sur le titre de l'une des colonnes disponibles (par exemple, tris threads par le nombre de conflits), sélectionnez une des threads et puis basculez vers le graphique de plus d'informations de conflit du thread via le menu contextuel.

Corriger le problème et les résultats de comparaison

Après avoir trouvé la cause des conflits de verrouillage de l'application, vous pouvez commenter la section critique mmlock et réexécutez le profilage :

for (i = myid*PerProcessorChunk; 
     i < (myid+1)*PerProcessorChunk; 
     i++) {
  // EnterCriticalSection(&mmlock);
  for (j=0; j<SIZE; j++) {
    for (k=0; k<SIZE; k++) {
      C[i][j] += A[i][k]*B[k][j];
    }
  }
  // LeaveCriticalSection(&mmlock);
}

Vous pouvez vous y attendre le nombre de conflits pour la diminuer et de profilage en effet du code modifié rapports qu'un conflit de verrouillage, comme dans figure 9-.

image: Summary View of Profiling Results for Fixed Code
La figure 9 affichage Résumé des résultats de profil pour le code des

Nous pouvons également comparer les résultats de performances précédent et nouveau dans Visual Studio. Pour ce faire, sélectionnez les deux fichiers dans l'Explorateur de performances (Sélectionner un fichier, appuyez sur la touche MAJ ou Ctrl, puis sélectionnez un autre), puis avec le bouton droit et sélectionnez les rapports de performances de comparaison.

Un rapport de comparaison s'affiche, comme dans figure 10 . Dans l'exemple d'application, vous pouvez visualiser ce nombre de conflits inclusive de la fonction MatMult chutée de 1,003 à 0.

image: Comparison Report
La figure 10 rapport comparatif

Autres méthodes de collecte de données

Si vous créez votre session de performance pour l'échantillonnage ou instrumentation de profilage, vous pouvez toujours convertir ultérieurement au mode d'accès concurrentiel. Pour faire rapidement est d'utiliser le menu mode profilage dans l'Explorateur de performances. Commencez par sélectionner le mode que vous souhaitez être en, et vous êtes bon atteindre.

Vous pouvez également accéder par le biais de la définition de propriétés de votre session. Pointez sur la session dans l'Explorateur de performances, avec le bouton droit pour afficher le menu contextuel, puis cliquez sur Propriétés. L'onglet Général de pages de propriétés vous permet de que contrôler sur votre mode de session de profilage et les autres paramètres de profilage.

Une fois votre mode de profilage est définie pour Concurrency (ou d'échantillonnage, dans notre exemple), vous pouvez soit lancement de votre application (il est déjà dans votre liste de cibles si vous avez utilisé l'Assistant Performance, ou vous pouvez l'ajouter il manuellement) ou vous pouvez attacher à une application qui est en cours d'exécution. Explorateur de performances vous donne les contrôles pour effectuer ces tâches, comme le montre la figure 11, .

image: Profiling Controls of Performance Explorer
La figure 11 profil des contrôles de l'Explorateur de performances

L'interface utilisateur de Visual Studio automatise plusieurs des étapes nécessaires pour collecter les données de profilage. Toutefois, il est possible de collecter des données de profilage à l'aide des outils de ligne de commande, ce qui peuvent être utiles pour l'exécution automatique et les scripts.

Pour lancer votre application en rivalité mode profilage, ouvrez l'invite de commande Visual Studio (qui met tous les fichiers binaires du Générateur de profils dans votre chemin d'accès, soit x 86 ou x64 des outils) et puis effectuez le des opérations suivantes :

  1. VSPerfCmd.exe /start:CONCURRENCY, RESOURCEONLY /output : <YourOutputFile>

  2. /Launch VSPerfCmd.exe : < Your Application > /args: “ < Your Application Arguments > ”

  3. Exécutez votre scénario.

  4. VSPerfCmd.exe / détacher

    • Cette étape n'est pas nécessaire si votre application se termine, mais elle entraîne sans incidence pour pouvoir l'ajouter à vos scripts.
  5. /Shutdown VSPerfCmd.exe

    Vous pouvez maintenant ouvrir YourOutputFile.VSP dans Visual Studio pour l'analyse.

Si vous disposez d'une application qui s'exécute déjà, vous pouvez attacher le profileur à l'aide de ces étapes :

  1. VSPerfCmd.exe /start:CONCURRENCY, RESOURCEONLY /output : <YourOutputFile>
  2. VSPerfCmd.exe / joindre : < nom de processus ou PID >
  3. Exécutez votre scénario.
  4. VSPerfCmd.exe / détacher
  5. /Shutdown VSPerfCmd.exe

Une explication plus détaillée des options de ligne de commande disponibles, consultez msdn.microsoft.com/library/bb385768(VS.100) de .

Une variété de vues de Visual Studio vous permettre de contrôler étroitement les données collectées. Certains affichages offrent une image de la durée de vie d'application dans son ensemble, alors que d'autres personnes se concentrent sur les conflits spécifiques, utilisez que vous pouvez rencontrer plus précieux.

Lorsque vous analysez les résultats de profilage, vous pouvez utiliser double-clique sur les transitions d'une vue à l'autre par le biais de liens hypertexte, ou les menus contextuels, ou vous pouvez passer directement à n'importe quel affichage disponible par l'intermédiaire d'une liste déroulante-menu déroulant. La figure 12 décrit brièvement chacune des vues.

La figure 12 vues d'analyse,

Affichage Description
Résumé Informations de résumé sont présentées à servir de point de départ pour votre investigation. Il s'agit de la première vue de que vous voir et qu'il s'ouvre automatiquement une fois une session de profilage terminée et le fichier de résultats est prêt.
Appeler l'arborescence Une arborescence des appels agrégée de toutes les piles de contention. Vous pouvez visualiser ici les piles sont responsables de vos conflits.
Modules Une liste de modules qui contiennent des fonctions, chaque ce qui entraîne un conflit. Chaque module possède une liste de fonctions pertinentes et le nombre de conflits détectés.
Appelant/appelé Un affichage de trois volets que la présente fonction F, toutes les fonctions qui appellent F et les fonctions sont appelées par F (uniquement les appels abouti à conflits, bien sûr).
Fonctions Une liste de toutes les fonctions détectées sur une pile de conflits avec les données associées.
Lignes Les lignes de la fonction dans le code source.
Détails sur la ressource Plus d'informations sur une ressource spécifique (par exemple, un verrou), tous les threads qui ont été bloquées s'affiche qu'il contient pendant la durée de vie d'application.
Détails des threads Plus d'informations sur un thread spécifique, montrant toutes les ressources (telles que les verrous) le thread a été bloquée sur.
Conflit Afficher à l'arborescence des appels est similaire, mais ici arborescences des appels sont séparés par des conflits entre ressources. En d'autres termes, cette vue présente un ensemble d'arborescences d'appel, chaque conteneur piles qui n'a été bloqué sur une ressource spécifique.
Marques de Liste des marques d'automatiquement et manuellement enregistrés, où chaque Mark est associée à son horodatage et les valeurs des compteurs de Windows.
Processus Une liste de processus inspectés, où chaque processus dispose d'une liste de ses threads, et chaque thread est attribuée par le nombre de conflits, qu'il s'est produit et la longueur de temps bloqué synthétisée.
Détails de la fonction Les détails concernant une fonction spécifique, y compris les fonctions qu'il les appels et les données collectées.
Adresses IP Une liste de pointeurs d'instruction dans laquelle conflit s'est produite (Hé bien, une liste des fonctions comme EnterCriticalSection, WaitForSingleObject et ainsi de suite, car Voici où conflits qui se produit en fait).

La contention des ressources nouvelles profilage des fonctionnalités de Visual Studio doit vous aider à découvrir des problèmes de performances par à l'aide de la synchronisation de threads dans le code et vous permettent d'améliorer votre application runtime en modifiant, réduisant ou éliminant synchronisation inutile.

Maxim Goldin est ingénieur de conception de logiciel senior chez Microsoft. Il a travaillé sur l'équipe d'ingénierie de Visual Studio depuis 2003. Vous pouvez le contacter à mgoldin@microsoft.comde et il les blogs à blogs.msdn.com/b/mgoldin de.

Pour plus d'informations sur les performances investigation mouvements voir mon blog de l'Assistant Publier à blogs.msdn.com/b/mgoldin/archive/2010/04/22/resource-contention-concurrency-profiling-in-visual-studio-2010-performance-investigation-flows.aspx de .

Je remercie les experts techniques suivants d'avoir relu cet article : Steve Carroll, Anne Galaeva, Daryush Laqab, Marc Popkin-Paine, Chris Schmich et Colin Thomsen