Introdução: por que perfilhar código C++?
Otimização sem medições é adivinhação. Mesmo desenvolvedores experientes frequentemente erram ao supor qual parte do código é a mais lenta. O perfilamento é a única maneira científica de responder à pergunta: "Onde exatamente o programa gasta mais tempo?".
Neste artigo, abordaremos ferramentas práticas para perfilamento de código C++ no Linux: gprof, perf e Valgrind (Callgrind). Você aprenderá como executar profilers, interpretar seus relatórios e encontrar gargalos reais.
1. Perfilamento com gprof
Preparação do código
gprof é o profiler mais simples e acessível. Para usá-lo, é necessário compilar o programa com a flag -pg:
g++ -pg -O2 main.cpp -o my_programExecute o programa. Ele será executado um pouco mais devagar que o normal, mas criará um arquivo gmon.out com os dados de perfilamento. Em seguida, execute o gprof:
./my_programgprof my_program gmon.out > report.txtExemplo de análise
Considere um programa simples com duas funções:
#include <iostream>#include <cmath>
void slowFunction() { double sum = 0.0; for (int i = 0; i < 100000000; ++i) { sum += std::sin(i) * std::cos(i); } std::cout << "Sum: " << sum << std::endl;}
void fastFunction() { int count = 0; for (int i = 0; i < 1000; ++i) { for (int j = 0; j < 1000; ++j) { count += (i * j) % 3; } } std::cout << "Count: " << count << std::endl;}
int main() { slowFunction(); fastFunction(); return 0;}Após executar o gprof, no relatório veremos uma tabela com o tempo de execução de cada função:
Flat profile:
Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 99.0 1.98 1.98 1 1980.0 1980.0 slowFunction() 1.0 0.02 0.02 1 20.0 20.0 fastFunction()A conclusão é óbvia: slowFunction() ocupa 99% do tempo. O gargalo é a chamada das funções trigonométricas sin e cos dentro do loop.
Limitações do gprof
- Funciona apenas com programas compilados com
-pg - Não mostra o tempo em funções inline
- Não é adequado para aplicações multithread (sem configurações adicionais)
2. Perfilamento com perf (Linux)
Execução básica
perf é uma ferramenta poderosa para perfilamento em nível de kernel. Ela não requer recompilação do programa e funciona com qualquer binário (mesmo com otimização -O3):
# Instalação (se não tiver)sudo apt install linux-tools-common linux-tools-generic
# Perfilamento contando ciclos da CPUperf stat ./my_program
# Gravação de eventos para análise detalhadaperf record ./my_programperf reportExemplo com perf stat
Para o mesmo programa, perf stat mostrará:
Performance counter stats for './my_program':
1,987.45 msec task-clock # 1.000 CPUs utilized 10 context-switches # 5.028 /sec 0 cpu-migrations # 0.000 /sec 105 page-faults # 52.832 /sec 5,234,567,890 cycles # 2.634 GHz 9,876,543,210 instructions # 1.89 insn per cycle 1,234,567,890 branches # 621.234 M/sec 10,000,000 branch-misses # 0.81% of all branches
1.987456789 seconds time elapsedMétricas-chave