Diagnosticar retrasos de la interfaz de usuario causados por las extensiones

Cuando la interfaz de usuario deja de responder, Visual Studio examina la pila de llamadas del subproceso de la interfaz de usuario, empezando por la hoja y trabajando hacia la base. Si Visual Studio determina que un marco de pila de llamadas pertenece a un módulo que forma parte de una extensión instalada y habilitada, muestra una notificación.

UI delay (unresponsiveness) Notification

La notificación informa al usuario de que el retraso de la interfaz de usuario (es decir, la falta de respuesta en la interfaz de usuario) podría haber sido el resultado del código de una extensión. También proporciona al usuario opciones para deshabilitar la extensión o las notificaciones futuras de esa extensión.

En este documento se describe cómo puede diagnosticar lo que en el código de extensión está causando notificaciones de retraso de la interfaz de usuario.

Nota:

No use la instancia experimental de Visual Studio para diagnosticar retrasos en la interfaz de usuario. Algunas partes del análisis de pila de llamadas necesarias para las notificaciones de retraso de la interfaz de usuario se desactivan cuando se usa la instancia experimental, lo que significa que es posible que no se muestren las notificaciones de retraso de la interfaz de usuario.

Una introducción al proceso de diagnóstico es la siguiente:

  1. Identifique el escenario de desencadenador.
  2. Reinicie VS con el registro de actividad activado.
  3. Inicie el seguimiento de ETW.
  4. Desencadene la notificación para que aparezca de nuevo.
  5. Detenga el seguimiento de ETW.
  6. Examine el registro de actividad para obtener el identificador de retraso.
  7. Analice el seguimiento ETW mediante el identificador de retraso del paso 6.

En las secciones siguientes, se describen estos pasos con más detalle.

Identificación del escenario de desencadenador

Para diagnosticar un retraso de la interfaz de usuario, primero debe identificar qué (secuencia de acciones) hace que Visual Studio muestre la notificación. Esto es para que pueda desencadenar la notificación más adelante con el registro activado.

Reinicio de VS con el registro de actividad activado

Visual Studio puede generar un "registro de actividad" que proporciona información útil al depurar un problema. Para activar el registro de actividad en Visual Studio, abra Visual Studio con la /log opción de línea de comandos. Una vez iniciado Visual Studio, el registro de actividad se almacena en la siguiente ubicación:

%APPDATA%\Microsoft\VisualStudio\<vs_instance_id>\ActivityLog.xml

Para obtener más información sobre cómo puede encontrar el identificador de instancia de VS, consulte Herramientas para detectar y administrar instancias de Visual Studio. Usaremos este registro de actividad más adelante para obtener más información sobre los retrasos de la interfaz de usuario y las notificaciones relacionadas.

Inicio del seguimiento de ETW

Puede usar PerfView para recopilar un seguimiento ETW. PerfView proporciona una interfaz fácil de usar tanto para recopilar un seguimiento ETW como para analizarlo. Use el siguiente comando para recopilar un seguimiento:

Perfview.exe collect C:\trace.etl /BufferSizeMB=1024 -CircularMB:2048 -Merge:true -Providers:*Microsoft-VisualStudio:@StacksEnabled=true -NoV2Rundown /kernelEvents=default+FileIOInit+ContextSwitch+Dispatcher

Esto habilita el proveedor "Microsoft-VisualStudio", que es el proveedor que Visual Studio usa para eventos relacionados con las notificaciones de retraso de la interfaz de usuario. También especifica la palabra clave para el proveedor de kernel que PerfView puede usar para generar la vista Pilas de tiempo de subproceso .

Desencadene la notificación para que aparezca de nuevo

Una vez que PerfView ha iniciado la recopilación de seguimiento, puede usar la secuencia de acciones del desencadenador (del paso 1) para que la notificación aparezca de nuevo. Una vez que se muestra la notificación, puede detener la recopilación de seguimiento para que PerfView procese y genere el archivo de seguimiento de salida.

Detener el seguimiento de ETW

Para detener la recopilación de seguimiento, simplemente use el botón Detener colección en la ventana PerfView. Después de detener la recopilación de seguimiento, PerfView procesará automáticamente los eventos ETW y generará un archivo de seguimiento de salida.

Examen del registro de actividad para obtener el identificador de retraso

Como se mencionó anteriormente, puede encontrar el registro de actividad en %APPDATA%\Microsoft\VisualStudio<vs_instance_id>\ActivityLog.xml. Cada vez que Visual Studio detecta un retraso de la interfaz de usuario de extensión, escribe un nodo en el registro de actividad con UIDelayNotifications como origen. Este nodo contiene cuatro fragmentos de información sobre el retraso de la interfaz de usuario:

  • Identificador de retraso de la interfaz de usuario, un número secuencial que identifica de forma única un retraso de la interfaz de usuario en una sesión de VS.
  • El identificador de sesión, que identifica de forma única la sesión de Visual Studio de inicio a cierre.
  • Indica si se ha mostrado una notificación para el retraso de la interfaz de usuario
  • La extensión que probablemente provocó el retraso de la interfaz de usuario.
<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>

Nota:

No todos los retrasos de la interfaz de usuario producen una notificación. Por lo tanto, siempre debe comprobar el valor notificación que se muestra para identificar correctamente el retraso correcto de la interfaz de usuario.

Después de encontrar el retraso correcto de la interfaz de usuario en el registro de actividad, anote el identificador de retraso de la interfaz de usuario especificado en el nodo. Usará el identificador para buscar el evento ETW correspondiente en el paso siguiente.

Análisis del seguimiento etw

A continuación, abra el archivo de seguimiento. Puede hacerlo mediante la misma instancia de PerfView o iniciando una nueva instancia y estableciendo la ruta de acceso de carpeta actual en la parte superior izquierda de la ventana en la ubicación del archivo de seguimiento.

Setting the folder path in Perfview

A continuación, seleccione el archivo de seguimiento en el panel izquierdo y ábralo seleccionando Abrir en el menú contextual o haga clic con el botón derecho.

Nota:

De forma predeterminada, PerfView genera un archivo Zip. Al abrir trace.zip, descomprime automáticamente el archivo y abre el seguimiento. Para omitir esto, desactive el cuadro Zip durante la recopilación de seguimiento. Sin embargo, si planea transferir y usar seguimientos en diferentes máquinas, se recomienda encarecidamente desactivar la casilla Zip . Sin esta opción, los archivos PDB necesarios para los ensamblados Ngen no acompañarán el seguimiento y, por tanto, los símbolos de los ensamblados Ngen no se resolverán en la máquina de destino. (Consulte esta entrada de blog para obtener más información sobre PDB para ensamblados Ngen).

PerfView puede tardar varios minutos en procesar y abrir el seguimiento. Una vez abierto el seguimiento, aparece una lista de varias "vistas" en él.

PerfView trace summary view

En primer lugar, usaremos la vista Eventos para obtener el intervalo de tiempo del retraso de la interfaz de usuario:

  1. Para abrir la vista Eventos , seleccione el Events nodo en el seguimiento y elija Abrir en el menú contextual o haga clic con el botón derecho.
  2. Seleccione "Microsoft-VisualStudio/ExtensionUIUnresponsiveness" en el panel izquierdo.
  3. Presione Entrar

La selección se aplica y todos los ExtensionUIUnresponsiveness eventos se muestran en el panel derecho.

Selecting events in Events view

Cada fila del panel derecho corresponde a un retraso de la interfaz de usuario. El evento incluye un valor de "Id. de retraso" que debe coincidir con el identificador de retraso en el registro de actividad del paso 6. Puesto que ExtensionUIUnresponsiveness se desencadena al final del retraso de la interfaz de usuario, la marca de tiempo del evento (aproximadamente) marca la hora de finalización del retraso de la interfaz de usuario. El evento también contiene la duración del retraso. Podemos restar la duración de la marca de tiempo final para obtener la marca de tiempo de cuando se inició el retraso de la interfaz de usuario.

Calculating the UI delay time-range

En la captura de pantalla anterior, por ejemplo, la marca de tiempo del evento es 12.125.679 y la duración del retraso es 6.143.085 (ms). Así,

  • El inicio del retraso es 12.125.679 - 6.143.085 = 5.982.594.
  • El intervalo de tiempo de retraso de la interfaz de usuario es de 5.982.594 a 12.125.679.

Una vez que tengamos el intervalo de tiempo, podemos cerrar la vista Eventos y abrir la vista Pilas de tiempo de subproceso (con startStop Activities). Esta vista es especialmente útil porque a menudo las extensiones que bloquean el subproceso de la interfaz de usuario simplemente esperan en otros subprocesos o en una operación enlazada a E/S. Por lo tanto, la vista Pila de CPU, que es la opción de uso para la mayoría de los casos, puede que no capture el tiempo que el subproceso dedica a bloquear, ya que no usa la CPU durante ese tiempo. Las pilas de tiempo de subproceso resuelven este problema mostrando correctamente el tiempo bloqueado.

Thread Time (with StartStop Activities) Stacks node in PerfView summary view

Al abrir la vista Pilas de tiempo de subproceso, elija el proceso de devenv para iniciar el análisis.

Thread Time Stacks view for UI delay analysis

En la vista Pilas de tiempo de subproceso, en la parte superior izquierda de la página, puede establecer el intervalo de tiempo en los valores calculados en el paso anterior y presionar Entrar para que las pilas se ajusten a ese intervalo de tiempo.

Nota:

Determinar qué subproceso es el subproceso de interfaz de usuario (inicio) puede ser contraintuitivo si la recopilación de seguimiento se inicia después de que Visual Studio ya esté abierta. Sin embargo, los primeros elementos de la pila del subproceso de interfaz de usuario (inicio) son los archivos DLL del sistema operativo (ntdll.dll y kernel32.dll) seguidos de devenv!? y, a continuaciónmsenv!?, . Esta secuencia puede ayudar a identificar el subproceso de la interfaz de usuario.

Identifying the startup thread

También puede filtrar aún más esta vista si solo incluye pilas que contienen módulos del paquete.

  • Establezca GroupPats en texto vacío para quitar cualquier agrupación agregada de forma predeterminada.
  • Establezca IncPats para incluir parte del nombre del ensamblado además del filtro de proceso existente. En este caso, debe ser devenv; UIDelayR2.

Setting GroupPath and IncPath in Thread Time Stacks view

PerfView tiene instrucciones detalladas en el menú Ayuda que puede usar para identificar cuellos de botella de rendimiento en el código. Además, los vínculos siguientes proporcionan más información sobre cómo usar las API de subprocesos de Visual Studio para optimizar el código:

También puede usar los nuevos analizadores estáticos de Visual Studio para extensiones (paquete NuGet aquí), que proporcionan instrucciones sobre los procedimientos recomendados para escribir extensiones eficaces. Consulte una lista de analizadores de VS SDK y analizadores de subprocesos.

Nota:

Si no puede solucionar la falta de respuesta debido a las dependencias sobre las que no tiene control (por ejemplo, si la extensión tiene que llamar a servicios vs sincrónicos en el subproceso de la interfaz de usuario), nos gustaría saberlo. Si es miembro de nuestro programa de partners de Visual Studio, puede ponerse en contacto con nosotros mediante el envío de una solicitud de soporte técnico para desarrolladores. De lo contrario, use la herramienta "Notificar un problema" para enviar sus comentarios e incluirlos "Extension UI Delay Notifications" en el título. Incluya también una descripción detallada del análisis.