Introducción: ¿por qué es importante perfilar código C++?
\nC++ es uno de los lenguajes de programación más rápidos, pero incluso en él se puede escribir código lento. A menudo, los desarrolladores pasan horas optimizando partes del programa que no lo necesitan, guiándose por la intuición. El perfilado es un enfoque científico para la optimización: se mide dónde el programa pasa más tiempo y se mejoran específicamente esas áreas.
\nPara los programadores principiantes de C++, el perfilado puede parecer complejo, pero en realidad las herramientas básicas se aprenden en una tarde. En este artículo, analizaremos tres herramientas populares: gprof, perf y Valgrind, y aprenderemos a interpretar sus resultados.
¿Qué es el perfilado y qué métodos existen?
\nEl perfilado es la recopilación de datos sobre el funcionamiento de un programa durante su ejecución. Existen dos enfoques principales:
\n- \n
- Perfilado por instrumentación — se añaden "sondas" especiales al código del programa (por ejemplo,
gprof). Desventaja: ralentiza la ejecución del programa. \n - Perfilado por muestreo — a intervalos regulares "observa" el programa y registra qué función se está ejecutando en ese momento (por ejemplo,
perf). Casi no ralentiza el programa. \n
También existen herramientas para buscar fugas de memoria (Valgrind) y analizar la caché. Para empezar, es suficiente dominar gprof y perf.
Herramienta 1: gprof — el clásico del perfilado
\ngprof es un perfilador integrado para GCC. Funciona en dos etapas: recopilación de datos y su análisis.
Cómo usar gprof
\nPrimero, compile el programa con la bandera -pg:
g++ -pg -o my_program my_program.cpp\nEjecute el programa:
\n./my_program\nDespués de la ejecución, aparecerá el archivo gmon.out. Ahora ejecute gprof:
gprof my_program gmon.out > report.txt\nAbra report.txt y observe la tabla:
Flat profile:\nEach sample counts as 0.01 seconds.\n % cumulative self self total\n time seconds seconds calls ms/call ms/call name\n 60.00 0.06 0.06 10000 0.01 0.01 slow_function\n 30.00 0.09 0.03 5000 0.01 0.02 medium_function\n 10.00 0.10 0.01 1 10.00 10.00 main\nEn la columna % time se muestra el porcentaje de tiempo que ocupó la función. En nuestro ejemplo, slow_function es el principal candidato para la optimización.
Consejo: Para programas pequeños, gprof es excelente. Para proyectos grandes, puede dar datos inexactos debido a las optimizaciones del compilador.
Herramienta 2: perf — potente muestreador para Linux
\nperf es un perfilador integrado en el núcleo de Linux. Funciona mediante el método de muestreo y casi no ralentiza el programa. Es ideal para sistemas en producción.
Uso básico de perf
\nCompile el programa con símbolos de depuración (bandera -g):
g++ -g -o my_program my_program.cpp\nInicie el perfilado:
\nperf record ./my_program\nDespués de que el programa termine, vea el informe:
\nperf report\nVerá una interfaz interactiva. Al hacer clic en una función, puede ver qué líneas de código se ejecutaron con más frecuencia. Ejemplo de salida:
\nSamples: 1K of event 'cycles'\nEvent count (approx.): 250000000\nOverhead Command Shared Object Symbol\n 45.32% my_program my_program [.] slow_function\n 30.15% my_program my_program [.] medium_function\n 12.50% my_program libc-2.31.so [.] malloc\n 8.03% my_program my_program [.] main\nImportante: perf requiere permisos de root para recopilar datos del núcleo