Laboratorio 3 Solución de problemas de rendimiento y GC con dotnet-dump en Linux

Se aplica a:   .NET Core 2.1, .NET Core 3.1, .NET 5

En este artículo se presenta cómo usar la herramienta dotnet-dump para capturar y analizar volcados de .NET Core y usarlos para generar informes relacionados con dotnet-gcdump GC en Linux.

Requisitos previos

Los requisitos mínimos para seguir estos laboratorios de solución de problemas son los siguientes:

  • Una ASP.NET Core para demostrar problemas de rendimiento de CPU baja y cpu alta y problemas de bloqueo.
  • El depurador lldb, instalado y configurado para cargar la extensión SOS cuando se abre un archivo de volcado de memoria.

Si ha seguido las partes anteriores de esta serie, debe tener lista la siguiente configuración:

  • Nginx está configurado para hospedar dos sitios web:
    • El primero escucha las solicitudes mediante el encabezado de host myfirstwebsite ( ) y las solicitudes de enrutamiento a la aplicación de demostración ASP.NET Core que escucha en el puerto http://myfirstwebsite 5000.
    • El segundo escucha las solicitudes mediante el encabezado de host de buggyamb ( ) y las solicitudes de enrutamiento ASP.NET Core la segunda aplicación de ejemplo de errores que escucha en el puerto http://buggyamb 5001.
  • Ambas ASP.NET Core deben ejecutarse como servicios que se reinician automáticamente cuando se reinicia el servidor o la aplicación deja de responder.
  • El firewall local de Linux está habilitado y configurado para permitir el tráfico SSH y HTTP.

Nota

Si la configuración no está lista, vaya a "Part 2 Create and run ASP.NET Core apps."

Objetivo de este laboratorio

En Lab 2.2 Capture dump files by using ProcDump, you used ProcDump, and tested it to capture core dump files either manually or by monitoring the memory usage.

En esta parte, aprenderá a usar dotnet-dump para capturar y analizar archivos de volcado de datos principales sin ningún depurador nativo. A continuación, aprenderá a usar para generar informes relacionados con GC que puede abrir en un equipo basado Windows dotnet-gcdump usuario.

Dotnet-dump

dotnet-dump es otra forma de recopilar y analizar archivos de volcado de datos principales sin tener que usar un depurador nativo, como lldb en Linux. Esta herramienta también permite ejecutar comandos SOS para analizar bloqueos y problemas relacionados con el recolector de elementos no utilizados (GC). Dotnet-dump está disponible solo en el SDK de .NET Core 3.0 y versiones posteriores.

Nota

Dotnet-dump no es un depurador nativo. Por lo tanto, algunas características, como mostrar los marcos de pila nativos, no están disponibles en esta herramienta.

Si no ha instalado dotnet-dump, puede instalarlo ahora ejecutando el siguiente comando:

dotnet tool install -g dotnet-dump

Para capturar manualmente los archivos de volcado de datos principales, puede usar el dotnet-dump collect comando. Por ejemplo, dotnet-dump collect -p 11724. La herramienta recopilará los mismos archivos de volcado de datos principales recopilados mediante createdump o ProcDump.

La característica más importante de dotnet-dump es que se puede usar para abrir archivos de volcado de .NET Core y ejecutar comandos SOS, igual que lldb. Todavía tendrás que configurar símbolos e instalar la extensión SOS para poder analizar un archivo de volcado de datos con dotnet-dump.

Nota

Si ha trabajado anteriormente con lldb, ya debería haber configurado los símbolos e instalado SOS. Por lo tanto, debería poder abrir los mismos archivos de volcado de versión de .NET Core sin tener que volver a descargar los símbolos. Si abre un archivo de volcado de versión de .NET Core diferente para el que aún no se han descargado los símbolos, tendrá que descargar los símbolos de esa versión de .NET Core antes de iniciar el análisis.

Recopilar archivos de volcado de datos principales mediante dotnet-dump

Para recopilar un archivo de volcado de memoria mediante dotnet-dump, usará el dotnet-dump collect <PID> comando. Determinar el PID debe ser una tarea fácil para usted en este momento. Sin embargo, si necesita ayuda, este comando incluye un ps parámetro. El dotnet-dump ps comando enumera los procesos dotnet de los que puede recopilar un archivo de volcado.

Si intenta ejecutar el comando, encontrará algunos dotnet-dump ps resultados inesperados.

Captura de pantalla del comando ps.

En esta lista se muestran dos procesos. Sin embargo, uno de ellos se muestra como un proceso elevado y su ruta de acceso no se puede determinar mediante el dotnet-dump comando ps. Para encontrar su ruta de acceso, examine la información de la línea de comandos del proceso ejecutando el cat /proc/<PID>/cmdline comando.

Nota

En este comando, reemplace por el identificador de proceso real del proceso de destino, como <PID> se muestra en el siguiente resultado de ejemplo. Es posible que recuerde el directorio /proc/ especial de secciones anteriores y que un proceso en Linux se pueda ver como otra carpeta debajo de ese directorio (con el nombre de id. de proceso). Para encontrar todos los detalles sobre un proceso, examine la estructura de directorios <PID> / /proc/.

Captura de pantalla del comando cat cmdline.

Como se muestra en esta captura de pantalla, el resultado del primer comando ( ) le indica que esta es la primera cat /proc/6164/cmdline demostración ASP.NET Core aplicación. El resultado del segundo comando ( cat /proc/15586/cmdline ) le indica que esta es la aplicación de errores.

Aunque el comando no pudo recuperar la ruta de acceso del proceso, todavía debería poder generar los archivos dotnet-dump ps de volcado necesarios para solucionar problemas. Intente capturar un archivo de volcado de memoria mediante el dotnet-dump collect comando. En primer lugar, pruebe la aplicación de demostración para la que la herramienta pudo mostrar la ruta de acceso del proceso. Ejecutar dotnet-dump collect -p 6164 (el PID de proceso será diferente al probar el ejercicio).

Captura de pantalla del comando collect.

La generación del archivo de volcado de memoria se realiza correctamente. Ahora, intente recopilar un archivo de volcado de memoria para la aplicación de errores para la que la herramienta no pudo enumerar la ruta de acceso del proceso cuando usó el dotnet-dump ps comando. Ejecute dotnet-dump collect -p 15586 y observe que se produce un error inesperado.

Captura de pantalla del comando de recopilación dotnet.

Se devuelve el siguiente mensaje de error:

(13): permiso denegado /tmp/dotnet-diagnostic-15586-2544688-socket

Cuando observó que el comando no podía obtener la ruta de acceso del proceso, es posible que haya sospechado que intentar generar el archivo de volcado principal dotnet-dump ps produciría un error.

Desde el mensaje de error anterior, puede determinar que hay un problema de permisos implicado. Pero, ¿cuál es la diferencia entre los dos procesos, el primero hospeda la aplicación de ejemplo .NET 5 y el segundo hospeda la aplicación .NET Core 3? Compare los archivos de servicio de cada proceso. Debe poder detectar la diferencia con relativa facilidad: la cuenta de usuario que ejecuta cada proceso es diferente.

Captura de pantalla de dos comandos.

El lado izquierdo de la lista corresponde a la primera aplicación de demostración, en la que todo funciona bien, y la aplicación se ejecuta como (o la cuenta de usuario que usó al configurar el entorno y inició <User Name> sesión). El lado derecho corresponde a la aplicación de errores, para la que se ha fallado la colección de archivos de volcado. y la aplicación se ejecuta como usuario de www-data.

La solución a este problema se describe en la página GitHub oficial.

Como resumen, si está ejecutando el proceso de servicio como un usuario diferente al de la cuenta que usó para iniciar sesión, debe ejecutar el comando de la dotnet-dump collect siguiente manera.

Captura de pantalla del comando sudo.

Este es el formato del comando:

sudo -H -u <user name of service> bash -c "<full path to dotnet tools>/dotnet-dump collect -p <PID> -o <output path>"

Puede determinar la ruta de acceso completa de la herramienta dotnet-dump mediante el whereis dotnet-dump comando.

Captura de pantalla del comando whereis.

La ruta de acceso de salida debe ser un directorio donde el usuario tenga el permiso De escritura. Normalmente, puede crear el directorio en el directorio /tmp y, a continuación, copiar el archivo de volcado en el directorio principal más adelante.

Abrir y analizar archivos de volcado de datos principales mediante dotnet-dump

Para este ejercicio, no tiene que capturar un nuevo archivo de volcado de datos. En su lugar, puede abrir uno de los archivos de volcado de datos anteriores que capturó mediante createdump. Si lo prefiere, puede abrir un archivo de volcado de memoria que capturó mediante dotnet-dump.

Para abrir el archivo de volcado mediante dotnet-dump, ejecute (el nombre del archivo de volcado de memoria dotnet-dump analyze ~/dumps/coredump.manual.2.11724 será diferente en el equipo). Este es el mismo motor de depurador administrado que usó anteriormente en lldb. Si los símbolos están configurados correctamente y SOS está instalado correctamente, puede ejecutar cualquier comando SOS, lo mismo que puede con lldb. En la siguiente lista, puede ver el clrstack comando en acción.

Captura de pantalla del comando clrstack.

Hay dos cosas que debe tener en cuenta:

  • Dado que no se trata de un depurador nativo, no puede ejecutar comandos de depurador nativo lldb, como el comando de lectura de memoria que se le indicó que usara en lldb anteriormente. Solo puede ejecutar comandos SOS.
  • La finalización automática no funciona. En lldb, puede empezar a escribir un comando y, a continuación, presionar la tecla TAB para completar automáticamente el comando, igual que lo hizo en la línea de comandos y el shell. La característica no funciona para dotnet-dump. Sin embargo, esto no debe afectar al aprendizaje.

Mientras tenga abierto el archivo de volcado principal, aproveche esta oportunidad para practicar algunos comandos SOS nuevos.

¿Cómo puede comprobar el uso de la CPU en un volcado de datos? El threadpool comando puede ayudar a revelar esta información. Informa del "uso total de CPU del servidor" (no solo para el proceso que se está depurando), sino que también proporciona una idea general del consumo de recursos en el equipo en el momento en que se generó el archivo de volcado de memoria. La siguiente captura de pantalla muestra que el uso total de LA CPU del servidor era de alrededor del 94 %.

Captura de pantalla del comando threadpool.

Nota

El servidor que se usó para crear estas listas estaba equipado con dos CPU. Por este motivo, genera informes como este.

El mismo resultado también muestra la configuración del grupo de subprocesos y, en la lista anterior, que había siete subprocesos de trabajo disponibles y seis de ellos en ejecución. Esta información sería útil al solucionar problemas de configuración del grupo de subprocesos.

¿Desea agrupar la pila de llamadas de todos los subprocesos en ejecución y mostrar una presentación combinada, similar al panel Visual Studio Pilas paralelas? Ejecute pstacks para obtener un resultado similar.

Captura de pantalla del comando pstacks.

Para comprender mejor los comandos SOS disponibles, abra la Ayuda de SOS y revise cada comando individualmente para familiarizarse con el poder de la depuración de SOS.

Dotnet-dump es útil si instalar lldb no es una opción para usted. El aprendizaje continúa mediante la introducción de otro enfoque para analizar los montón de GC.

Dotnet-gcdump

Dotnet-gcdump es otra herramienta útil. Está disponible en .NET Core 3.1 o versiones posteriores.

La idea detrás de esta herramienta es que no necesita un volcado de proceso completo para poder completar una investigación en muchos escenarios en los que principalmente desea ver el montón administrado. Por lo tanto, ¿por qué no capturar la información del montón y generar un informe sobre ella? Lo más importante es que los archivos de volcado de GC generados por esta herramienta son portátiles y se pueden analizar en un Windows equipo. Dado que este tipo de archivo de volcado contiene solo la información de montón de GC, no puede abrirlo en lldb para investigar los subprocesos o las pilas de llamadas de subprocesos. Pero puede abrirlo en PerfView o en Visual Studio.

Esto puede sonar promisorio, pero... Hay una cosa que debe tener en cuenta: desencadena una colección de GC de gen 2 en el proceso para recopilar Dotnet-gcdump los datos que necesita. Use esta herramienta cuidadosamente en producción. No lo use a menos que sepa que definitivamente tiene que hacerlo.

¿Cuándo podría necesitar usar esta herramienta? Si el proceso ya está en un estado no responde (colgado) y no hay nada que recuperar de la situación y tiene previsto reiniciar la aplicación. A continuación, puede capturar un gcdump antes del reinicio para que tenga al menos un conjunto de información para analizar en una fase posterior.

La información capturada por esta herramienta será útil para las siguientes tareas:

  • Compare el número de objetos por tipo en el montón.
  • Analizar las raíces del objeto.
  • Determine qué objetos tienen una referencia a qué tipos.
  • Otro análisis estadístico sobre objetos en el montón.

Si aún no ha instalado esta herramienta, haga lo mismo ahora. Solo tiene que ejecutar el siguiente comando:

dotnet tool install --global dotnet-gcdump

Recopilar gcdump con el comando dotnet-gcdump

La misma regla se aplica a la que se aplica a la herramienta dotnet-dump: si ejecuta el proceso para un usuario diferente, debe ejecutar el comando dotnet-gcdump con el siguiente formato:

sudo -H -u <user name of service> bash -c "<full path to dotnet tools>/dotnet-gcdump collect -p <PID> -o <output path>"

Consulte la sección Recopilar archivos de volcado de datos principales mediante dotnet-dump si este comando no le resulta familiar.

Ahora debería tener todo lo que necesita para recopilar información del proceso mediante la herramienta. El objetivo será recopilar dos conjuntos de datos, tal como lo hizo con los archivos de volcado de datos principales. El proceso de destino se está ejecutando de nuevo para un usuario diferente. Por lo tanto, tendrás que usar el formato "bash" para el comando de inicio.

Estos son los pasos:

  1. Para reproducir el problema de rendimiento, ejecute seis solicitudes en la página Lento mediante la herramienta Generador de carga que se incluye en el ASP.NET Core web.

  2. Recopile el primer gcdump ejecutando el siguiente comando:

    sudo -H -u www-data bash -c "/home/<User Name>/.dotnet/tools/dotnet-gcdump collect -p 15586 -o /tmp/gcreport1.gcdump"

    Nota: En este comando, reemplace el PID por el suyo propio.

  3. Espere entre 5 y 10 segundos y, a continuación, recopile el segundo gcdumpby ejecutando el siguiente comando:

    sudo -H -u www-data bash -c "/home/<User Name>/.dotnet/tools/dotnet-gcdump collect -p 15586 -o /tmp/gcreport2.gcdump

    Nota: En este comando, reemplace el PID por el PID original.

Recuerde que está solucionando un problema de rendimiento. Es una buena idea tener varios conjuntos de datos para poder comparar cómo evolucionó el montón administrado con el tiempo. El resultado de estos comandos será que se generen dos archivos gcdump.

Captura de pantalla del comando sudo h.

Crear informes a partir de archivos gcdump

Copie los dos archivos gcdump en el equipo basado Windows y ábralos en Visual Studio 2019. La siguiente captura de pantalla muestra los resultados de comparación de ambos archivos gcdump tomados para esta lista. Como puede ver, hay una gran diferencia entre los valores del tipo de objeto String. También puede obtener información de raíz acerca de los objetos.

Captura de pantalla de los archivos de informe.

Puede ser información útil.

Como alternativa, puede abrir informes gcdump en PerfView.

Captura de pantalla del archivo de informe.

Si solo tiene que ver el montón administrado, esta podría ser la opción más rápida para usted. Solo recuerda tener cuidado cuando usas en producción, ya que, como se mencionó anteriormente, desencadenará un GC completo en el proceso y esto puede provocar dotnet-gcdump pausas largas. Use esta herramienta en producción cuidadosamente y solo cuando sea necesario cuando solucione un problema de memoria.