Diagnostiquer les retards de l’interface utilisateur causés par les extensions
Lorsque l’interface utilisateur ne répond plus, Visual Studio examine la pile des appels du thread d’interface utilisateur, en commençant par la feuille et en travaillant vers la base. Si Visual Studio détermine qu’une trame de pile d’appels appartient à un module qui fait partie d’une extension installée et activée, il affiche une notification.
La notification informe l’utilisateur que le délai de l’interface utilisateur (autrement dit, l’absence de réponse dans l’interface utilisateur) a peut-être été le résultat du code d’une extension. Il fournit également à l’utilisateur des options permettant de désactiver l’extension ou les notifications futures pour cette extension.
Ce document décrit comment diagnostiquer ce qui se trouve dans votre code d’extension provoque des notifications de retard d’interface utilisateur.
Remarque
N’utilisez pas l’instance expérimentale Visual Studio pour diagnostiquer les retards de l’interface utilisateur. Certaines parties de l’analyse de pile des appels requises pour les notifications de retard d’interface utilisateur sont désactivées lors de l’utilisation de l’instance expérimentale, ce qui signifie que les notifications de retard de l’interface utilisateur peuvent ne pas être affichées.
Voici une vue d’ensemble du processus de diagnostic :
- Identifiez le scénario de déclencheur.
- Redémarrez VS avec la journalisation d’activité activée.
- Démarrez ETW Tracing.
- Déclenchez la notification pour qu’elle s’affiche à nouveau.
- Arrêtez ETW Tracing.
- Examinez le journal d’activité pour obtenir l’ID de délai.
- Analysez la trace ETW à l’aide de l’identifiant de délai de l’étape 6.
Dans les sections suivantes, nous allons suivre ces étapes plus en détail.
Identifier le scénario de déclencheur
Pour diagnostiquer un délai d’interface utilisateur, vous devez d’abord identifier ce qui (séquence d’actions) entraîne l’affichage de la notification par Visual Studio. Cela vous permet de déclencher la notification ultérieurement avec l’activation de la journalisation.
Redémarrer VS avec la journalisation d'activité activée
Visual Studio peut générer un « journal d’activité » qui fournit des informations utiles lors du débogage d’un problème. Pour activer la journalisation des activités dans Visual Studio, ouvrez Visual Studio avec l’option de ligne de commande /log
. Une fois Visual Studio démarré, le journal d’activité est stocké à l’emplacement suivant :
%APPDATA%\Microsoft\VisualStudio\<vs_instance_id>\ActivityLog.xml
Pour en savoir plus sur la façon dont vous pouvez trouver votre ID d’instance VS, consultez Tools pour détecter et gérer des instances Visual Studio. Nous allons utiliser ce journal d’activité ultérieurement pour en savoir plus sur les retards de l’interface utilisateur et les notifications associées.
Démarrage ETW Tracing
Vous pouvez utiliser PerfView pour collecter une trace ETW. PerfView fournit une interface facile à utiliser pour collecter une trace ETW et l’analyser. Utilisez la commande suivante pour collecter une trace :
Perfview.exe collect C:\trace.etl /BufferSizeMB=1024 -CircularMB:2048 -Merge:true -Providers:*Microsoft-VisualStudio:@StacksEnabled=true -NoV2Rundown /kernelEvents=default+FileIOInit+ContextSwitch+Dispatcher
Cela active le fournisseur « Microsoft-VisualStudio », qui est celui utilisé par Visual Studio pour les événements liés aux notifications de retard lié à l'interface utilisateur. Il spécifie également le mot-clé du fournisseur du noyau que PerfView peut utiliser pour générer la vue Piles de temps des threads.
Déclencher la notification pour qu’elle s’affiche à nouveau
Une fois que PerfView a démarré la collection de traces, vous pouvez utiliser la séquence d’actions de déclencheur (à l’étape 1) pour que la notification apparaisse à nouveau. Une fois la notification affichée, vous pouvez arrêter la collecte de traces pour PerfView afin de traiter et de générer le fichier de trace de sortie.
Arrêter ETW Tracing
Pour arrêter la collecte de traces, utilisez simplement le bouton Arrêter la collection dans la fenêtre PerfView. Après avoir arrêté la collecte de traces, PerfView traite automatiquement les événements ETW et génère un fichier de trace de sortie.
Examiner le journal d’activité pour obtenir l’ID de délai
Comme mentionné précédemment, vous pouvez trouver le journal d’activité dans %APPDATA%\Microsoft\VisualStudio<vs_instance_id>\ActivityLog.xml. Chaque fois que Visual Studio détecte un délai d’interface utilisateur d’extension, il écrit un nœud dans le journal d’activité avec UIDelayNotifications
comme source. Ce nœud contient quatre informations sur le délai d’interface utilisateur :
- ID de délai d’interface utilisateur, nombre séquentiel qui identifie de façon unique un retard d’interface utilisateur dans une session VS
- ID de session, qui identifie de manière unique votre session Visual Studio du début à la fermeture
- Indique si une notification a été affichée ou non pour le retard de l'interface utilisateur
- Extension qui a probablement provoqué le retard de l’interface utilisateur
<entry>
<record>271</record>
<time>2018/02/03 12:02:52.867</time>
<type>Information</type>
<source>UIDelayNotifications</source>
<description>A UI delay (Delay ID = 0) has been detected. (Session ID=16e49d4b-26c2-4247-ad1c-488edeb185e0; Blamed extension="UIDelayR2"; Notification shown? Yes.)</description>
</entry>
Remarque
Tous les retards de l’interface utilisateur n’entraînent pas de notification. Par conséquent, vous devez toujours vérifier la notification affichée ? valeur pour identifier correctement le délai approprié de l’interface utilisateur.
Après avoir trouvé le délai d’interface utilisateur correct dans le journal d’activité, notez l’ID de délai d’interface utilisateur spécifié dans le nœud. Vous allez utiliser l’ID pour rechercher l’événement ETW correspondant à l’étape suivante.
Analyser la trace ETW
Ensuite, ouvrez le fichier de trace. Pour ce faire, vous pouvez utiliser la même instance de PerfView ou en démarrant une nouvelle instance et en définissant le chemin du dossier actif en haut à gauche de la fenêtre à l’emplacement du fichier de trace.
Sélectionnez ensuite le fichier de trace dans le volet gauche et ouvrez-le en choisissant Ouvrir dans le menu contextuel ou cliquez avec le bouton droit.
Remarque
Par défaut, PerfView génère une archive Zip. Lorsque vous ouvrez trace.zip, il décompose automatiquement l’archive et ouvre la trace. Vous pouvez ignorer ce problème en décochant la case Zip lors de la collecte de traces. Toutefois, si vous envisagez de transférer et d’utiliser des traces sur différents ordinateurs, nous vous recommandons vivement de décocher la case Zip. Sans cette option, les fichiers PDB requis pour les assemblys Ngen n’accompagnent pas la trace et les symboles des assemblys Ngen ne seront donc pas résolus sur l’ordinateur de destination. (Consultez ce billet de blog pour plus d’informations sur les PDB pour les assemblages NGen.)
PerfView peut prendre plusieurs minutes pour traiter et ouvrir la trace. Une fois la trace ouverte, une liste de différentes « vues » apparaît sous celle-ci.
Nous allons d’abord utiliser la vue Événements pour obtenir l’intervalle de temps du délai de l'interface utilisateur :
- Ouvrez la vue Événements en sélectionnant le nœud
Events
sous la trame et en choisissant Ouvrir dans le menu contextuel ou en utilisant le clic droit. - Sélectionnez «
Microsoft-VisualStudio/ExtensionUIUnresponsiveness
» dans le volet gauche. - Appuyez sur Entrée
La sélection est appliquée et tous les événements ExtensionUIUnresponsiveness
sont affichés dans le volet droit.
Chaque ligne du volet droit correspond à un délai d’interface utilisateur. L’événement inclut une valeur « ID de délai » qui doit correspondre à l’ID de retard dans le journal d’activité de l’étape 6. Étant donné que ExtensionUIUnresponsiveness
est déclenché à la fin du délai de l’interface utilisateur, l’horodatage de l’événement marque approximativement l’heure de fin du délai de l’interface utilisateur. L’événement contient également la durée du délai. Nous pouvons soustraire la durée de l’horodatage de fin pour obtenir l’horodatage du début du délai d’interface utilisateur.
Dans la capture d’écran précédente, par exemple, l’horodatage de l’événement est de 12 125,679 et la durée du délai est de 6 143,085 (ms). Donc
- Le début du délai est de 12 125,679 - 6 143,085 = 5 982,594.
- L’intervalle de temps de retard de l’interface utilisateur est de 5 982,594 à 12 125,679.
Une fois que nous avons l'intervalle temporel, nous pouvons fermer la vue Événements et ouvrir la vue Temps des threads (avec les activités de démarrage/arrêt). Cette vue est particulièrement pratique, car souvent les extensions qui bloquent le thread d’interface utilisateur attendent simplement d’autres threads ou une opération liée aux E/S. Par conséquent, la vue de pile d’UC, qui est l’option go-to pour la plupart des cas, peut ne pas capturer le temps que le thread passe au blocage, car il n’utilise pas le processeur pendant ce temps. Les Stacks de temps des threads résolvent ce problème en affichant correctement le temps bloqué.
Lors de l’ouverture de la vue des piles temporelles du thread, choisissez le processus devenv pour démarrer l’analyse.
Dans la vue Piles de temps de thread, en haut à gauche de la page, vous pouvez définir l’intervalle de temps sur les valeurs que nous avons calculées à l’étape précédente et appuyer sur Entrée afin que les piles soient ajustées à cette plage de temps.
Remarque
Déterminer quel thread est le thread d’interface utilisateur (démarrage) peut être contre-intuitif si la collection de traces est démarrée après que Visual Studio est déjà ouvert. Toutefois, les premiers éléments de la pile du thread d’interface utilisateur (démarrage) sont toujours des DLL du système d’exploitation (ntdll.dll et kernel32.dll) suivies de devenv!?
, puis de msenv!?
. Cette séquence peut aider à identifier le thread d’interface utilisateur.
Vous pouvez également filtrer davantage cette vue en incluant uniquement les piles qui contiennent des modules à partir de votre package.
- Définissez GroupPats sur du texte vide pour supprimer tout regroupement ajouté par défaut.
- Définissez IncPats pour inclure une partie de votre nom d’assembly en plus du filtre de processus existant. Dans ce cas, il doit être devenv ; UIDelayR2.
PerfView contient des conseils détaillés dans le menu Aide que vous pouvez utiliser pour identifier les goulots d’étranglement des performances dans votre code. En outre, les liens suivants fournissent plus d’informations sur l’utilisation des API de thread De Visual Studio pour optimiser votre code :
https://github.com/Microsoft/vs-threading/blob/main/doc/index.md
https://github.com/Microsoft/vs-threading/blob/main/doc/cookbook_vs.md
Vous pouvez également utiliser les nouveaux analyseurs statiques Visual Studio pour les extensions (package NuGet ici), qui fournissent des conseils sur les meilleures pratiques d’écriture d’extensions efficaces. Consultez la liste des analyseurs VSSDK et des analyseurs de threading .
Remarque
Si vous ne parvenez pas à résoudre le manque de réponse en raison de dépendances sur lesquelles vous n’avez pas le contrôle (par exemple, si votre extension doit appeler des services VS synchrones sur le thread de l’interface utilisateur), nous aimerions en être informés. Si vous êtes membre de notre programme Partenaire Visual Studio, vous pouvez nous contacter en envoyant une demande de support aux développeurs. Sinon, utilisez l’outil « Signaler un problème » pour envoyer vos commentaires et inclure "Extension UI Delay Notifications"
dans le titre. Incluez également une description détaillée de votre analyse.