LINUX

Cómo utilizar la herramienta de creación de perfiles Gprof en Linux (tutorial)

A medida que el código se vuelve más y más grande, también aumenta el número de funciones y llamadas a funciones anidadas. Por lo tanto, para analizar el rendimiento de dicho programa, es necesario comprender qué funciones están tardando en ejecutarse. Además, el análisis de funciones individuales también debe proporcionar una clara distinción entre el tiempo que toma la función principal y las otras funciones llamadas desde dentro de la función principal.

Las herramientas de software que se utilizan para este tipo de análisis de rendimiento se conocen popularmente como perfiladores. En este tutorial, discutiremos un generador de perfiles basado en Linux llamado gprof.

Todos los ejemplos presentados en este artículo se prueban en Ubuntu, bash 4.2.45 y gprof 2.23.2.

Configuración y uso de Gprof

Estos son algunos de los pasos necesarios para descargar y configurar un entorno para gprof:

  • Si aún no está instalado, descargue e instale gprof ejecutando ‘apt-get install binutils
  • Para comprobar que gprof está instalado correctamente, ejecute el comando gprof y debería dar algún error como ‘a.out: No such file or directory’.
  • Suponiendo que el compilador que se está usando es gcc o cc, compile su código con la opción ‘-pg’ para que el ejecutable incluya código adicional para fines de creación de perfiles.
  • Ejecute el programa de forma normal. Cuando el programa termina, se producirá un archivo llamado ‘gmon.out’ (datos del generador de perfiles) en el mismo directorio desde el que se ejecutó el programa.
  • Utilice el generador de perfiles gprof para procesar estos datos del generador de perfiles (gmon.out) y producir análisis de rendimiento y estadísticas del programa legibles por humanos.

Aquí hay un código de ejemplo que queremos perfilar:

#include<stdio.h>

void some_other_test(void)
{
printf("n Inside the function some_other_test() n");
int i = 0;
for(;i<=0XFFFF;i++);
}

void yet_another_test(void)
{
printf("n Inside the function yet_other_test() n");
int i = 0;
for(;i<=0XFFFFFFF;i++);
}

void another_test(void)
{
printf("n Inside the function another_test() n");
int i = 0;
for(;i<=0XFFF;i++);

yet_another_test();
}

void test(void)
{
printf("n Inside the function test() n");
int i = 0;
for(;i<=0XFFFFFF;i++);

another_test();
}

int main(void)
{
printf("n Inside the function main() n");
int i = 0;
for(;i<=0XFFFFF;i++);

test();
some_other_test();

return 0;
}

Tenga en cuenta que el código anterior es solo un ejemplo ficticio que contiene bucles for para simular el consumo de tiempo en el procesamiento de funciones.

Una vez que el código está en su lugar, el primer paso es compilar el código. Aquí sabrás como podrás hacerlo :

$ gcc -Wall -pg profile.c -o profile

Entonces puede ver que el código se guardó en un archivo llamado ‘perfil.c’ y el nombre del archivo de salida es ‘perfil’.

Una vez que se produjo el ejecutable llamado ‘perfil’, se ejecutó como cualquier otro programa:

$ ./profile

Inside the function main()

Inside the function test()

Inside the function another_test()

Inside the function yet_other_test()

Inside the function some_other_test()

Para que pueda ver que el programa se ejecutó correctamente. Además, produjo un archivo llamado ‘gmon.out’ en el mismo directorio.

$ ls gmon.out
gmon.out

Ahora, use la utilidad gprof de la siguiente manera:

$ gprof profile gmon.out > output

Entonces puede ver que el nombre del ejecutable y gmon.out se proporcionaron como argumentos para el comando gprof y la salida se redirigió a un archivo llamado ‘salida’. Este archivo contiene todo el análisis estadístico del rendimiento del ‘perfil’ del programa en forma legible por humanos.

El contenido de la salida se divide en tipos de información: perfil plano y gráfico de llamada.

Perfil plano

Aquí está el análisis estadístico en forma de perfil plano:

análisis estadístico gprof

Las estadísticas que se muestran arriba se conocen como perfil plano. Aquí está la explicación (tomada de la salida del archivo) de lo que significa cada columna:

    • % hora – El porcentaje del tiempo total de ejecución del programa utilizado por esta función.
    • Segundos acumulativos – Una suma acumulada del número de segundos contabilizados por esta función y los enumerados arriba.
    • Segundos propios – El número de segundos contabilizados solo por esta función. Este es el tipo principal de este listado.
    • Llamadas – El número de veces que se invocó esta función, si esta función está perfilada, en caso contrario, en blanco.
    • Auto ms / llamada – El número promedio de milisegundos gastados en esta función por llamada, si esta función está perfilada, en caso contrario, en blanco.
    • Total ms / llamada – El número promedio de milisegundos gastados en esta función y su descendiente por llamada, si esta función está perfilada, en caso contrario, en blanco.
    • Nombre – El nombre de la función. Este es el tipo menor de este listado. El índice muestra la ubicación de la función en el listado de gprof. Si el índice está entre paréntesis, muestra dónde aparecería en la lista gprof si se imprimiera.

Gráfico de llamadas

Aquí está el análisis estadístico en forma de gráfico de llamadas:

gráfico de llamada de análisis estadístico gprof

Esta tabla describe el árbol de llamadas del programa y se ordenó por la cantidad total de tiempo dedicado a cada función y sus hijos. Cada entrada de esta tabla consta de varias líneas. La línea con el número de índice en el margen izquierdo muestra la función actual. Las líneas arriba enumeran las funciones que llamaron a esta función, y las líneas debajo enumeran las funciones que esta llamó.

Aquí está la explicación (tomada de la salida del archivo) de lo que significa cada columna:

    • Índice – Un número único asignado a cada elemento de la tabla. Los números de índice se ordenan numéricamente. El número de índice está impreso al lado de cada nombre de función, por lo que es más fácil buscar dónde está la función en la tabla.
    • % hora – Este es el porcentaje del tiempo «total» que se dedicó a esta función y sus hijos. Tenga en cuenta que debido a diferentes puntos de vista, funciones excluidas por opciones, etc., estos números NO sumarán el 100%.
    • Uno mismo – Esta es la cantidad total de tiempo dedicado a esta función. Para los padres de la función, esta es la cantidad de tiempo que se propagó directamente desde la función a este padre. Mientras que, para los hijos de la función, esta es la cantidad de tiempo que se propagó directamente del hijo a la función.
    • Niños – Ésta es la cantidad total de tiempo que sus hijos propagan en esta función. Para los padres de la función, esta es la cantidad de tiempo que se propagó de los hijos de la función a este padre. Mientras que, para los hijos de la función, esta es la cantidad de tiempo que se propagó de los hijos del niño a la función.
    • Llamado – Este es el número de veces que se llamó a la función. Si la función se llama a sí misma de forma recursiva, el número solo incluye las llamadas no recursivas y va seguido de un «+» y el número de llamadas recursivas. Para los padres de la función, este es el número de veces que este padre llamó a la función `/ ‘el número total de veces que se llamó a la función. Las llamadas recursivas a la función no se incluyen en el número después de `/ ‘. Mientras que, para los hijos de la función, este es el número de veces que la función llamó a este hijo `/ ‘el número total de veces que se llamó al hijo. Las llamadas recursivas realizadas por el niño no se enumeran en el número después de `/ ‘.
    • Nombre – El nombre de la función actual. El número de índice se imprime después. Si la función es miembro de un ciclo, el número de ciclo se imprime entre el nombre de la función y el número de índice. Para los padres de la función, este es el nombre del padre. El número de índice del padre se imprime después. Si el padre es miembro de un ciclo, el número de ciclo se imprime entre el nombre y el número de índice. Para los hijos de la función, este es el nombre del niño. El número de índice del niño se imprime a continuación. Si el niño es miembro de un ciclo, el número de ciclo se imprime entre el nombre y el número de índice.

Toda la explicación mencionada anteriormente también está presente en el archivo de salida generado por gprof. Lo he mencionado aquí para facilitar a los lectores.

Nota: Toda esta explicación se produce en el archivo de salida cada vez que se ejecuta gprof. Entonces, una vez que haya entendido los detalles, puede usar la opción de línea de comandos gprof -b. Para leer más opciones de la línea de comandos, lea página de manual de gprof.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Cerrar