x
1

Profilers



En ingeniería de software el análisis de rendimiento, comúnmente llamado profiling o perfilaje, es la investigación del comportamiento de un programa de ordenador usando información reunida desde el análisis dinámico del mismo. El objetivo es averiguar el tiempo dedicado a la ejecución de diferentes partes del programa para detectar los puntos problemáticos y las áreas dónde sea posible llevar a cabo una optimización del rendimiento (ya sea en velocidad o en consumo de recursos).[1]​ Un profiler puede proporcionar distintas salidas, como una traza de ejecución o un resumen estadístico de los eventos observados.[2]

Usualmente el Profiling es utilizado durante el desarrollo de software como método para la depuración y optimización de los algoritmos, esta práctica vista de esta manera es buena, pero es vista más como una actividad interna que suele carecer de objetividad y veracidad cuando no es evaluado por personal realmente especializado y en el entorno adecuado para ello.[3]

El profiling se puede llevar a cabo en el código fuente o sobre un binario ejecutable mediante una herramienta llamada profiler.

Los profilers pueden clasificarse según la forma de recopilación de datos que utilicen, pudiendo destacar: basados en eventos, estadísticos, con instrumentación de código y como simulación.[2]

Las herramientas de análisis de rendimiento ya existían en las plataformas IBM S/360 y IBM System/370 de principios de 1970. Generalmente se basaba en un temporizador de interrupciones que se registraban en el programa de palabra de estado (Program status word, PSW) (que era un contador de programa y un registro de estado a la vez en estas arquitecturas) en intervalos establecidos para detectar hot spots en la ejecución del código.[4]​ Este fue un ejemplo temprano de muestreo en estadística que es un tipo que se verá a continuación. A principios de 1974, el simulador de conjunto de instrucciones permitió realizar trazas completas y otras funciones de supervisión del rendimiento.

Los programas analizadores de rendimiento en Unix se remontan al menos a 1979, cuando los sistemas Unix incluía la herramienta básica prof que aparece cada función y la cantidad de tiempo de ejecución del programa utilizado. En 1982, gprof extendió el concepto a un análisis llamado grafo de llamadas.[5]

En 1994, Amitabh Srivastava y Alan Eustace de Digital Equipment Corporation publican un artículo describiendo ATOM.[6]​ ATOM es una plataforma para convertir un programa en su propio profiler. Es decir, en tiempo de compilación, inserta el código en el programa a ser analizado. Ese código introducido produce salidas de datos de análisis. Esta técnica (modificar un programa para analizarse a sí mismo se conoce como instrumentación).

En 2004, tanto el "paper" de gprof como el de ATOM aparecieron en la lista de los 50 "papers" más influyentes de Programming Language Design and Implementation de todos los tiempos.[7]

Los profilers utilizan una amplia variedad de técnicas para recopilar datos, incluyendo: interrupciones por hardware, instrumentación de código, simulador de conjunto de instrucciones, hooking y contadores de rendimiento de hardware. El profiling es la técnica más usada dentro de la ingeniería de rendimiento.

Es común ver en este tipo de perfilado dos tecnologías: Instrumentación de código y muestreo; La instrumentación se basa en dejar que el compilador modifique cada llamada a una función, insertando algunas líneas de código que registra la llamada, el autor de la llamada y el tiempo que se requirió. Esta técnica viene de la mano con una sobrecarga significativa de trabajo, esto puede afectar de forma negativa en códigos donde se tenga una cantidad alta de funciones con tiempos de ejecución cortos. Sin embargo, esta técnica se encuentra limitada a solamente funciones o bloques simples, esto debido a razones de eficiencia. El muestreo por otro lado tiende a ser una opción menos invasiva, ya que funciona interrumpiendo el programa de forma periódica en intervalos pequeños, durante las interrupciones se registra el contador de eventos. Aunque este proceso es estadístico por naturaleza es importante denotar que a medida que la ejecución de nuestro código se prolongue, los resultados obtenidos serán mucho más precisos.

Una de las herramientas de perfilado más utilizada es gprof del paquete GNU binutils. Gprof usa la instrumentación de código y el muestreo para recoger un perfil funcional plano, así como un perfil de llamadas, también llamado gráfico de mariposa. Para poder perfilar, es necesario compilar nuestro código con ciertas instrucciones específicas (Para el compilador GCC existe -pg) y ejecutarlo una vez. Todo este proceso genera un archivo ilegible para nosotros con nombre ‘gmon.out’, este archivo será leído e interpretado por el propio gprof. El perfil plano obtenido contiene información acerca de los tiempos de ejecución de todas las funciones y la frecuencia con la que son llamadas.

El perfilado de funciones se vuelve inútil cuando el programa que deseamos analizar consta de funciones con gran tamaño que ocupan significativamente el tiempo de ejecución total del programa. Si la búsqueda de ‘hot spots’ dentro de nuestras funciones resulta ser extremadamente complicada, deberíamos contemplar a los perfiladores basados en líneas de código como lo puede ser OProfile. Cuando usamos OProfile solo tenemos un requisito previo, nuestros binarios deben contar con símbolos de depuración (esto usualmente se consigue con la bandera -g en nuestro compilador). De igual forma se debe iniciar un Daemon de perfilamiento que monitorizará a todo el equipo y recolectará datos de todos nuestros binarios activos. Nosotros como usuarios podemos extraer información de un binario en específico en cualquier otro momento. Esta información puede verse como un listado de fuentes anotadas en las que cada linea va acompañada del número de muestreos exitosos y del porcentaje relativo del total de los muestreos.

Sin embargo, este tipo de datos hay que tomarlos con discreción. Las tablas de símbolos generadas por el compilador deben ser consistentes para que la dirección de una instrucción de la máquina en la memoria pueda coincidir adecuadamente con la línea de origen correcta. El perfilaje basado en líneas de código es entonces una forma de perfilar que nos permite identificar los puntos calientes de un programa.

La salida que puede generar un profiler depende del mismo, generalmente son las siguientes:

Los profilers, que también son propios programas, analizar programas específicos mediante la recopilación de información sobre su ejecución. Basado en su granularidad de datos, la forma en que los profilers recopilan información, se clasifican en profilers basados en eventos o estadísticos. Ya que los profilers interrumpen la ejecución del programa para recopilar información, tienen una resolución finita en las mediciones de tiempo, los cuales se deben tomar como un subconjunto del total de información.

Los lenguajes de programación que se listan a continuación poseen un profiler basado en eventos:

Algunos profilers operan por muestreo. un profiler por muestreo prueba el "Program counter" del programa objetivo a intervalos regulares usando interrupciones del sistema operativo. Los profilers de muestreo son típicamente menos exactos numéricamente y específicos, pero permiten que el programa de destino funcione cerca de la velocidad máxima.

Algunos profilers "instrumentan" el programa objetivo con instrucciones adicionales para recopilar la información necesaria.

Instrumentar el programa puede causar cambios en el rendimiento del programa, que pueden causar resultados inexactos y heisenbugs. Instrumentar siempre tendrá algún impacto en la ejecución del programa, por lo general siempre es más lento. Sin embargo, la instrumentación puede ser muy específica y ser controlada cuidadosamente para tener un impacto mínimo. El impacto sobre un programa en particular depende de la colocación de puntos de instrumentación y el mecanismo que se utiliza para capturar la traza. El soporte de hardware para capturar la traza significa que en algunos objetivos, la instrumentación puede tener sólo una instrucción de máquina. El impacto de la instrumentación a menudo se puede deducir (es decir, eliminada por sustracción) a partir de los resultados.

gprof es un ejemplo de un profiler que utiliza tanto la instrumentación y el muestreo. La instrumentación se utiliza para recopilar información de las llamadas y los valores de tiempo real se obtienen mediante muestreo estadístico.

Esta técnica añade efectivamente instrucciones al programa de destino para recopilar la información requerida.

El efecto dependerá de qué información se está recopilando, del nivel de detalles de tiempo notificados y de si se utiliza la generación de perfiles de bloques básicos junto con la instrumentación.

La instrumentación es clave para determinar el nivel de control y la cantidad de resolución de tiempo disponible para los profilers. A continuación se enumeran todas las categorías:

Las opciones del intérprete de depuración permiten habilitar la recopilación de métricas de rendimiento cuando el intérprete se encuentra con cada declaración de destino. Los bytecodes, tablas de control e intérpretes JIT son tres ejemplos que suelen tener un control completo sobre la ejecución del código de destino, lo que permite la oportunidad de recolectar datos muy completos.

Esta relación se basa directamente con el rastreo distribuido. Pero ¿Qué es el rastreo distribuido? El rastreo distribuido es un método que se utiliza para perfilar o supervisar el resultado de una solicitud que se ejecuta en un sistema distribuido.

Para obtener una visión precisa de un sistema distribuido, estas distintas métricas de nodos deben agruparse en una vista holística, esto significa que los sistemas y sus propiedades sean analizados en su conjunto y no solo a través de las partes que los componen.

Lo más común, es que las solicitudes que son enviadas a los sistemas distribuidos no se meten con todo el conjunto de los nodos del sistema, sino que solo van hacia un conjunto o ruta en concreto a través de los nodos. Para esto, el rastreo distribuido indica las rutas a las que se accede y permite que los equipos las analicen y las supervisen.

El rastreo distribuido se instala en cada nodo del sistema para permitir que los equipos pidan información acerca de los nodos como su estado y rendimiento en base a la solicitud enviada.

Este método de rastreo analiza las solicitudes de la aplicación a medida que fluyen desde los dispositivos del frontend hasta los servicios del backend y las bases de datos. Los desarrolladores pueden utilizar el rastreo distribuido para solucionar las solicitudes que presentan una alta latencia o errores.

Las aplicaciones pueden construirse como monolitos o microservicios; una aplicación monolítica se desarrolla como una única unidad funcional.

En la arquitectura de microservicios, una aplicación se descompone en servicios modulares, cada uno de los cuales manejan una función central de la aplicación y suele ser gestionado por un equipo dedicado.

Los microservicios se utilizan para construir muchas aplicaciones modernas porque facilitan la prueba y el despliegue de actualizaciones rápidas y evitan un único punto de fallo. Sin embargo, puede ser difícil solucionar los problemas de los microservicios porque a menudo se ejecutan en un backend complejo y distribuido, y las solicitudes pueden implicar secuencias de múltiples llamadas a servicios por lo que al utilizar el rastreo distribuido de end to end, los desarrolladores pueden visualizar el recorrido completo de una solicitud, desde el frontend hasta el backend, y localizar cualquier fallo de rendimiento o cuello de botella que se haya producido por el camino.

Las plataformas de rastreo distribuido de end to end comienzan a recopilar datos en el momento en que se inicia una solicitud, como cuando un usuario envía un formulario en un sitio web. Esto desencadena la creación de un ID de rastreo único y un tramo inicial, llamado tramo padre, en la plataforma de rastreo.

Un rastreo representa toda la ruta de ejecución de la solicitud, y cada tramo en el rastreo representa una sola unidad de trabajo durante ese viaje, como una llamada a la API o una consulta a la base de datos. Cada vez que la solicitud entra en un servicio, se crea un tramo hijo de nivel superior. Si la solicitud realiza múltiples comandos o consultas dentro del mismo servicio, el tramo hijo de nivel superior puede actuar como padre de otros tramos hijos anidados debajo de él.

La plataforma de rastreo distribuido codifica cada tramo hijo con el ID de rastreo original y un ID de tramo único, datos de duración y error, y metadatos relevantes, como el ID del cliente o la ubicación.

Finalmente, todos los tramos se visualizan en un graph flame, con el tramo padre en la parte superior y los tramos hijos anidados debajo en orden de aparición.

Dado que cada tramo está cronometrado, los ingenieros pueden ver cuánto tiempo pasó la solicitud en cada servicio o base de datos, y priorizar sus esfuerzos de solución de problemas en consecuencia. Los desarrolladores también pueden utilizar el graph flame para determinar qué llamadas presentan errores.

Los ingenieros de frontend, backend y de fiabilidad del sitio utilizan el rastreo distribuido para lograr los siguientes beneficios:

A pesar de estas ventajas, existen algunos retos asociados a la implementación del rastreo distribuido:

Por el contrario, algunas plataformas modernas pueden ingerir todos sus rastros y basarse en decisiones basadas en la cola, lo que le permite capturar rastros completos que están etiquetados con atributos relevantes para el negocio, como el ID del cliente o la región.

Esto hace que sea más difícil determinar la causa raíz de una solicitud problemática y si un equipo del frontend o del backend debe solucionar el problema.

Un sistema de alto rendimiento puede generar millones de trazos por minuto, lo que dificulta la identificación y supervisión de los trazos más relevantes para sus aplicaciones. Afortunadamente, existen herramientas que te ayudan a sacar a la luz los datos de rendimiento más útiles.



Escribe un comentario o lo que quieras sobre Profilers (directo, no tienes que registrarte)


Comentarios
(de más nuevos a más antiguos)


Aún no hay comentarios, ¡deja el primero!