Introduction : pourquoi profiler le code C++ ?
L'optimisation sans mesures, c'est de la divination. Même les développeurs expérimentés se trompent souvent en supposant quelle partie du code est la plus lente. Le profilage est la seule méthode scientifique pour répondre à la question : « Où exactement le programme passe-t-il le plus de temps ? ».
Dans cet article, nous allons examiner les outils pratiques pour profiler du code C++ sous Linux : gprof, perf et Valgrind (Callgrind). Vous apprendrez à lancer les profileurs, à interpréter leurs rapports et à trouver les véritables goulots d'étranglement.
1. Profilage avec gprof
Préparation du code
gprof est le profileur le plus simple et le plus accessible. Pour son fonctionnement, vous devez compiler le programme avec l'option -pg :
g++ -pg -O2 main.cpp -o my_programLancez le programme. Il s'exécutera un peu plus lentement que d'habitude, mais créera un fichier gmon.out avec les données de profilage. Ensuite, lancez gprof :
./my_programgprof my_program gmon.out > report.txtExemple d'analyse
Considérons un programme simple avec deux fonctions :
#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;}Après avoir lancé gprof, nous verrons dans le rapport un tableau avec le temps d'exécution de chaque fonction :
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()La conclusion est évidente : slowFunction() occupe 99% du temps. Le goulot d'étranglement est l'appel aux fonctions trigonométriques sin et cos dans la boucle.
Limitations de gprof
- Fonctionne uniquement avec les programmes compilés avec
-pg - N'affiche pas le temps dans les fonctions inline
- Ne convient pas aux applications multithread (sans configuration supplémentaire)
2. Profilage avec perf (Linux)
Lancement de base
perf est un outil puissant pour le profilage au niveau du noyau. Il ne nécessite pas de recompilation du programme et fonctionne avec tous les binaires (même avec l'optimisation -O3) :
# Installation (si absent)sudo apt install linux-tools-common linux-tools-generic
# Profilage avec comptage des cycles processeurperf stat ./my_program
# Enregistrement des événements pour une analyse détailléeperf record ./my_programperf reportExemple avec perf stat
Pour le même programme, perf stat affichera :
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 elapsedLes points clés