Caso práctico: Aislar un problema de rendimiento (C#, Visual Basic, F#)
Use las herramientas de generación de perfiles para investigar problemas de rendimiento y aislar áreas problemáticas. En este caso práctico se usa una aplicación de ejemplo con problemas de rendimiento para demostrar cómo usar herramientas de generación de perfiles para mejorar la eficacia. Si desea comparar las herramientas de generación de perfiles, consulte ¿Qué herramienta debo elegir?
En este caso práctico se tratan estos temas:
- Cómo usar las herramientas de generación de perfiles de Visual Studio para analizar el rendimiento de las aplicaciones.
- Cómo interpretar los datos proporcionados por estas herramientas para identificar cuellos de botella en el rendimiento.
- Cómo aplicar estrategias prácticas para optimizar el código, centrarse en contadores de .NET, recuentos de llamadas y datos de tiempo.
Siga estos pasos y aplique estas técnicas a sus propias aplicaciones para que sean más eficaces y rentables.
Aislar un caso de estudio de problemas de rendimiento
La aplicación de ejemplo en este caso práctico es una aplicación ASP.NET que ejecuta consultas en una base de datos simulada. El ejemplo se basa en la muestra de diagnósticos.
El problema de rendimiento principal con la aplicación de ejemplo se encuentra en patrones de codificación ineficaces. La aplicación tiene un cuello de botella de rendimiento que afecta significativamente a su eficiencia. El problema incluye los siguientes síntomas:
Uso bajo de CPU: la aplicación muestra un uso de CPU bajo, lo que indica que la CPU no es el cuello de botella.
Alto número de subprocesos en el grupo de hilos: el número de subprocesos es relativamente alto y aumenta constantemente, lo que sugiere escasez de hilos en el grupo.
Respuesta de Aplicación Lenta: La aplicación responde lentamente debido a la falta de hilos disponibles para procesar nuevos elementos de trabajo.
El caso práctico tiene como objetivo abordar estos problemas mediante el uso de las herramientas de generación de perfiles de Visual Studio para analizar el rendimiento de la aplicación. Al comprender dónde y cómo se puede mejorar el rendimiento de la aplicación, los desarrolladores pueden implementar optimizaciones para que el código sea más rápido y eficaz. El objetivo final es mejorar el rendimiento general de la aplicación, lo que hace que sea más eficaz y rentable ejecutarse.
Desafío
La solución de los problemas de rendimiento de la aplicación .NET de ejemplo presenta varios desafíos. Estos desafíos se derivan de la complejidad de diagnosticar cuellos de botella de rendimiento. Los principales desafíos para solucionar los problemas descritos son los siguientes:
Diagnóstico de cuellos de botella de rendimiento: una de las principales dificultades es identificar con precisión las causas principales de los problemas de rendimiento. El bajo uso de CPU combinado con un rendimiento lento puede tener varios factores de contribución. Los desarrolladores deben usar herramientas de generación de perfiles de forma eficaz para diagnosticar estos problemas, lo que requiere comprender cómo funcionan estas herramientas y cómo interpretar su salida.
Restricciones de recursos y conocimientos: Teams puede enfrentar restricciones relacionadas con el conocimiento, la experiencia y los recursos. La generación de perfiles y la optimización de una aplicación requieren aptitudes y experiencia específicas, y no todos los equipos pueden tener acceso inmediato a estos recursos.
Abordar estos desafíos requiere un enfoque estratégico que combina el uso eficaz de herramientas de generación de perfiles, conocimientos técnicos y planificación y pruebas cuidadosas. El caso práctico tiene como objetivo guiar a los desarrolladores a través de este proceso, proporcionando estrategias e información para superar estos desafíos y mejorar el rendimiento de la aplicación.
Estrategia
Esta es una vista general del enfoque en este caso práctico:
- Iniciamos la investigación observando las métricas de los contadores de .NET al recopilar datos de rendimiento. Al igual que la herramienta Uso de CPU, la herramienta de contadores .NET de Visual Studio también es un buen punto de partida para una investigación de rendimiento.
- A continuación, para obtener información adicional para ayudar a aislar problemas o mejorar el rendimiento, considere la posibilidad de recopilar un seguimiento mediante una de las otras herramientas de generación de perfiles. Por ejemplo, eche un vistazo a los recuentos de llamadas y los datos de tiempo mediante la herramienta de Instrumentación.
La recopilación de datos requiere las siguientes tareas:
- Configuración de la aplicación para una versión de lanzamiento.
- Seleccione la herramienta Contadores de .NET del generador de perfiles de rendimiento (Alt+F2). (Los pasos posteriores implican la herramienta de instrumentación).
- En el Perfilador de Rendimiento, inicie la aplicación y recopile un registro.
Comprobación de contadores de rendimiento
Al ejecutar la aplicación, observamos los contadores en la herramienta Contadores de .NET. En el caso de las investigaciones iniciales, se incluyen algunas métricas clave para tener en cuenta:
CPU Usage
. Vea este contador para ver si se produce un problema de rendimiento con un uso elevado o bajo de cpu. Esto puede ser una pista de los tipos específicos de problemas de rendimiento. Por ejemplo:- Con un uso elevado de la CPU, use la herramienta Uso de CPU para identificar las áreas en las que es posible que podamos optimizar el código. Para ver un tutorial sobre esto, consulte Caso práctico: Guía para principiantes para optimizar el código.
- Con un uso bajo de CPU, use la herramienta Instrumentación para identificar recuentos de llamadas y tiempo medio de función en función del tiempo del reloj. Esto puede ayudar a identificar problemas como la contención o el agotamiento del grupo de subprocesos.
Allocation Rate
. Para una aplicación web que atiende solicitudes, la tarifa debe ser bastante estable.GC Heap Size
. Vigile este contador para ver si el uso de memoria está aumentando continuamente y hay una posible fuga de memoria. Si parece alta, use una de las herramientas de uso de memoria.Threadpool Thread Count
. Para una aplicación web que atiende solicitudes, vea este contador para ver si el recuento de subprocesos se mantiene estable o aumenta a una velocidad estable.
Este es un ejemplo que muestra cómo el CPU Usage
es bajo, mientras que el ThreadPool Thread Count
es relativamente alto.
Un número de subprocesos creciente constantemente con un uso bajo de CPU puede ser un indicador del colapso del grupo de subprocesos. El grupo de subprocesos se ve obligado a seguir generando nuevos subprocesos. El colapso del grupo de subprocesos se produce cuando el grupo no tiene subprocesos disponibles para procesar nuevos elementos de trabajo y a menudo hace que las aplicaciones respondan lentamente.
Según el bajo uso de CPU y el recuento de subprocesos relativamente alto, y trabajando en la teoría de un posible caso de agotamiento del grupo de subprocesos, cambie a utilizar la herramienta de instrumentación.
Investigar los recuentos de llamadas y los datos de tiempo
Echemos un vistazo a un seguimiento de la herramienta de instrumentación para intentar averiguar más sobre lo que sucede con los hilos.
Después de recopilar un seguimiento con la herramienta Instrumentación y cargarlo en Visual Studio, primero comprobamos la página de informe .diagsession inicial que muestra los datos resumidos. En el seguimiento recopilado, utilizamos el enlace Abrir detalles en el informe y luego seleccionamos Flame Graph.
La visualización de Flame Graph nos muestra que la función QueryCustomerDB
(que se muestra en amarillo) es responsable de una parte significativa del tiempo de ejecución de la aplicación.
Haga clic con el botón derecho en la función QueryCustomerDB
y elija Ver en el árbol de llamadas.
La ruta de código con el mayor uso de CPU en la aplicación se denomina el camino caliente . El icono de llama de la ruta de acceso activa () puede ayudar a identificar rápidamente los problemas de rendimiento que podrían mejorarse.
En la vista de árbol de llamadas, puede ver que la ruta crítica incluye la función QueryCustomerDB
, que apunta a un posible problema de rendimiento.
En relación con el tiempo invertido en otras funciones, los valores de Self y Avg Self para la función QueryCustomerDB
son muy altos. A diferencia de Total y Avg Total, los valores Self excluyen el tiempo invertido en otras funciones, por lo que este es un buen lugar para buscar el cuello de botella de rendimiento.
Sugerencia
Si los valores de Self fueran relativamente bajos en lugar de altos, probablemente querrá examinar las consultas reales a las que llama la función QueryCustomerDB
.
Haga doble clic en la función QueryCustomerDB
para mostrar el código fuente de la función.
public ActionResult<string> QueryCustomerDB()
{
Customer c = QueryCustomerFromDbAsync("Dana").Result;
return "success:taskwait";
}
Hacemos una pequeña investigación. Como alternativa, podemos ahorrar tiempo y dejar que Copilot hacer la investigación para nosotros.
Si usamos Copilot, seleccione Pregunte a Copilot en el menú contextual y escriba la siguiente pregunta:
Can you identify a performance issue in the QueryCustomerDB method?
Sugerencia
Puede usar comandos de barra diagonal como /optimize para ayudar a formar buenas preguntas para Copilot.
Copilot nos indica que este código llama a una API asincrónica sin usar await. Este es el patrón de código de sincronización sobre asincronía, que es una causa común del colapso del grupo de subprocesos y puede bloquear subprocesos.
Para resolver el problema, utilice await. En este ejemplo, Copilot proporciona la siguiente sugerencia de código junto con la explicación.
public async Task<ActionResult<string>> QueryCustomerDB()
{
Customer c = await QueryCustomerFromDbAsync("Dana");
return "success:taskwait";
}
Si ve problemas de rendimiento relacionados con las consultas de base de datos, puede usar la herramienta Database para investigar si determinadas llamadas son más lentas. Estos datos pueden indicar una oportunidad para optimizar las consultas. Para ver un tutorial que muestra cómo usar la herramienta Base de datos para investigar un problema de rendimiento, consulte Caso práctico: Guía para principiantes para optimizar el código. La herramienta Database admite .NET Core con ADO.NET o Entity Framework Core.
Para obtener visualizaciones en Visual Studio del comportamiento de hilos individuales, puede usar la ventana Pilas Paralelas durante la depuración. En esta ventana se muestran subprocesos individuales junto con información sobre los subprocesos que están esperando, subprocesos en los que están esperando y interbloqueos.
Para obtener información adicional sobre el agotamiento del grupo de subprocesos, consulte Detección del agotamiento del grupo de subprocesos.
Pasos siguientes
Los siguientes artículos y entradas de blog proporcionan más información para ayudarle a aprender a usar las herramientas de rendimiento de Visual Studio de forma eficaz.
- Caso práctico: Guía para principiantes sobre la optimización de código
- caso práctico: doble rendimiento en menos de 30 minutos
- mejorar el rendimiento de Visual Studio con la nueva herramienta de instrumentación