🔝 Retour au Sommaire
Le profiling est une technique qui permet d'analyser les performances de votre application en identifiant les parties du code qui consomment le plus de temps d'exécution ou de ressources. C'est un outil essentiel pour optimiser vos programmes.
- Identifier les goulots d'étranglement : découvrir quelles fonctions ralentissent votre application
- Optimiser de manière ciblée : concentrer vos efforts là où ils auront le plus d'impact
- Mesurer l'amélioration : vérifier que vos optimisations sont efficaces
- Comprendre le comportement : voir comment votre code s'exécute réellement
DProf (Delphi Profiler) est un outil de profiling compatible avec FreePascal sur Windows. Il analyse votre programme pendant son exécution et génère un rapport détaillé sur :
- Le temps passé dans chaque fonction
- Le nombre d'appels de chaque fonction
- La hiérarchie des appels (qui appelle quoi)
DProf nécessite :
- FreePascal/Lazarus installé sur Windows
- Votre projet doit être compilé avec des options spéciales
- L'outil DProf.exe (généralement fourni avec certaines distributions ou téléchargeable séparément)
Pour que votre programme puisse être profilé avec DProf, vous devez le compiler avec des informations de débogage spéciales.
-
Ouvrez votre projet
-
Allez dans Projet → Options du projet
-
Section Compilation et liaison :
- Cochez Générer les informations de débogage pour GDB
- Cochez Utiliser Heaptrc (optionnel, pour le suivi mémoire)
-
Section Options du compilateur personnalisées : Ajoutez ces options :
-pg
Compilez votre projet avec l'option -pg :
fpc -pg -gl MonProgramme.pasExplications des options :
-pg: Active l'instrumentation pour le profiling (génère du code supplémentaire qui enregistre les appels)-gl: Inclut les informations de ligne pour un débogage détaillé
Une fois compilé avec -pg, exécutez normalement votre programme :
MonProgramme.exePendant l'exécution, le programme génère automatiquement un fichier gmon.out dans le répertoire courant. Ce fichier contient toutes les données de profiling brutes.
Important : Le fichier gmon.out est écrasé à chaque exécution, donc sauvegardez-le si vous voulez comparer plusieurs sessions.
Sur Windows, vous utilisez gprof (GNU Profiler) pour lire le fichier gmon.out :
gprof MonProgramme.exe gmon.out > rapport_profiling.txtCette commande génère un rapport texte lisible.
Si vous avez DProf.exe :
dprof MonProgramme.exe gmon.outDProf ouvre une interface graphique qui affiche :
- La liste des fonctions triées par temps d'exécution
- Des graphiques de répartition du temps
- L'arbre d'appels (call graph)
Le rapport gprof contient trois sections principales :
% cumulative self self total
time seconds seconds calls ms/call ms/call name
45.20 1.35 1.35 100000 0.01 0.02 CalculComplexe
23.40 2.05 0.70 50000 0.01 0.01 TrierTableau
12.70 2.43 0.38 200000 0.00 0.00 RechercherElement
Colonnes expliquées :
- % time : Pourcentage du temps total passé dans cette fonction
- cumulative seconds : Temps cumulé depuis le début du rapport
- self seconds : Temps passé uniquement dans cette fonction (sans les sous-fonctions)
- calls : Nombre de fois que la fonction a été appelée
- self ms/call : Temps moyen par appel (en millisecondes)
- total ms/call : Temps moyen incluant les sous-fonctions
- name : Nom de la fonction
index % time self children called name
[1] 68.3 1.35 0.70 100000/100000 Principal [2]
0.70 0.00 50000/50000 TrierTableau [3]
-----------------------------------------------
1.35 0.70 100000/100000 Principal [2]
[2] 68.3 1.35 0.70 CalculComplexe [1]
0.70 0.00 50000/50000 TrierTableau [3]
Cette section montre :
- Qui appelle chaque fonction (parents)
- Quelles fonctions sont appelées (enfants)
- La distribution du temps entre appelants et appelés
Une liste alphabétique de toutes les fonctions avec leur index pour référence croisée.
Les fonctions à optimiser en priorité sont celles qui ont :
- Un % time élevé (>10% du temps total)
- Un grand nombre d'appels avec un temps self significatif
- Un temps total élevé même si le temps self est faible (elles appellent des fonctions lentes)
Si vous voyez :
45.20 1.35 1.35 100000 0.01 0.02 CalculComplexe
Interprétation :
- Cette fonction consomme 45% du temps total d'exécution
- Elle est appelée 100 000 fois
- Chaque appel prend en moyenne 0.01 ms
- Action : C'est la priorité numéro 1 pour l'optimisation
Si vous voyez :
2.10 2.50 0.06 1 60.00 2500.00 FonctionPrincipale
Interprétation :
- Cette fonction ne prend que 2% du temps directement
- Mais le temps total incluant les sous-fonctions est de 2500 ms
- Elle est appelée une seule fois
- Action : Le problème vient des fonctions qu'elle appelle, pas d'elle-même
Si une fonction est appelée très fréquemment avec un temps faible :
Avant :
for i := 1 to 10000 do
begin
valeur := ObtenirConfiguration('cle'); // Appelé 10000 fois
Traiter(valeur);
end;Après :
valeur := ObtenirConfiguration('cle'); // Appelé 1 fois
for i := 1 to 10000 do
begin
Traiter(valeur);
end;Si une fonction a un temps self élevé, améliorez son algorithme :
Avant (O(n²)) :
function Rechercher(tableau: array of Integer; valeur: Integer): Integer;
var
i: Integer;
begin
for i := 0 to High(tableau) do
if tableau[i] = valeur then
Exit(i);
Result := -1;
end;Après (utiliser une structure appropriée) :
// Utiliser un TDictionary pour O(1) au lieu de O(n)
var
dictionnaire: TDictionary<Integer, Integer>;Si une fonction calcule souvent la même chose :
var
CacheResultats: TDictionary<string, Integer>;
function CalculCouteux(parametre: string): Integer;
begin
if CacheResultats.ContainsKey(parametre) then
Exit(CacheResultats[parametre]); // Retour immédiat
// Calcul complexe uniquement si pas en cache
Result := FaireCalculComplexe(parametre);
CacheResultats.Add(parametre, Result);
end;- Utilisez des données réalistes, pas des données de test minimales
- Profilez le scénario d'utilisation typique de votre application
- Exécutez suffisamment longtemps pour obtenir des statistiques significatives
Compilez avec optimisations activées (-O2 ou -O3) pour profiler le code tel qu'il sera en production :
fpc -pg -O2 MonProgramme.pasLa règle des 80/20 s'applique : généralement 20% du code consomme 80% du temps. Concentrez-vous sur ces 20%.
Toujours profiler avant et après une optimisation pour vérifier son efficacité :
# Avant optimisation
gprof MonProgramme.exe gmon.out > avant.txt
# Après optimisation
gprof MonProgramme.exe gmon.out > apres.txt
# Comparer les deux fichiersLe profiling lui-même ajoute de l'overhead (surcoût). Le code avec -pg est environ 10-20% plus lent que le code normal. C'est normal, les temps relatifs restent corrects.
- Profiling de la mémoire : gprof mesure uniquement le temps CPU, pas l'utilisation mémoire
- Profiling multi-thread : les résultats peuvent être imprécis pour les applications multi-threadées
- Profiling temps réel : gprof compte les échantillons CPU, pas le temps réel (temps d'attente I/O non compté)
Pour des besoins avancés :
- Valgrind (via WSL) : profiling mémoire et cache
- Intel VTune : profiling très détaillé (commercial)
- Very Sleepy : profiler simple et gratuit pour Windows
- AQtime : profiler commercial avec interface graphique avancée
- Identifier le problème : "Mon programme est lent"
- Profiler : Compiler avec
-pget exécuter - Analyser : Identifier les fonctions critiques avec gprof
- Optimiser : Améliorer le code des fonctions identifiées
- Re-profiler : Vérifier l'amélioration
- Répéter : Continuer jusqu'à atteindre les performances souhaitées
program ExempleProfilage;
{$mode objfpc}{$H+}
uses
SysUtils;
function Fibonacci(n: Integer): Int64;
begin
if n <= 1 then
Exit(n)
else
Result := Fibonacci(n-1) + Fibonacci(n-2);
end;
function FibonacciOptimise(n: Integer): Int64;
var
a, b, i: Int64;
begin
if n <= 1 then Exit(n);
a := 0;
b := 1;
for i := 2 to n do
begin
Result := a + b;
a := b;
b := Result;
end;
end;
var
i: Integer;
debut, fin: TDateTime;
begin
WriteLn('Test Fibonacci récursif...');
debut := Now;
for i := 1 to 35 do
Fibonacci(i);
fin := Now;
WriteLn('Temps: ', MilliSecondsBetween(fin, debut), ' ms');
WriteLn('Test Fibonacci optimisé...');
debut := Now;
for i := 1 to 35 do
FibonacciOptimise(i);
fin := Now;
WriteLn('Temps: ', MilliSecondsBetween(fin, debut), ' ms');
end.# Compiler avec profiling
fpc -pg -gl ExempleProfilage.pas
# Exécuter
ExempleProfilage.exe
# Analyser
gprof ExempleProfilage.exe gmon.out > rapport.txtLe rapport montrera clairement que Fibonacci consomme beaucoup plus de temps que FibonacciOptimise, démontrant l'importance de l'algorithme choisi.
Le profiling avec DProf/gprof sur Windows est un outil puissant mais simple pour :
- Mesurer objectivement les performances
- Identifier précisément les problèmes
- Guider intelligemment vos optimisations
N'optimisez jamais à l'aveugle : mesurez d'abord, optimisez ensuite, et mesurez à nouveau pour confirmer l'amélioration.
Règle d'or : "On n'optimise pas ce qu'on ne mesure pas !"