Le profilage de code est un processus systématique d'analyse des performances d'un programme, permettant d'identifier les goulots d'étranglement et d'optimiser le fonctionnement de l'application. En Python, il existe de nombreux outils pour mesurer le temps d'exécution, la consommation mémoire et d'autres métriques critiques.
Les bases du profilage de code Python
Le profilage est une analyse dynamique du programme qui mesure :
- le temps d'exécution des fonctions individuelles
- le nombre d'appels de méthodes
- la consommation de mémoire vive
- la charge processeur
L'objectif principal du profilage est de déterminer les sections critiques du code qui ralentissent l'application et nécessitent une optimisation.
Quand utiliser le profilage
Le profilage est particulièrement pertinent dans les cas suivants :
Performances de l'application : Si le programme est plus lent que prévu, le profilage permet d'identifier les causes du ralentissement.
Consommation élevée de ressources : En cas d'utilisation excessive du CPU ou de la mémoire vive, le profilage montre quelles fonctions consomment le plus de ressources.
Préparation à la mise en production : Avant le déploiement d'applications critiques, le profilage permet de vérifier leur efficacité.
Optimisation des algorithmes : Lors du traitement de grands volumes de données ou de calculs complexes, le profilage révèle les algorithmes inefficaces.
Outils de profilage intégrés
Le module cProfile
cProfile est le profileur standard de Python, inclus dans l'interpréteur. Il convient à l'analyse générale des performances d'un programme.
import cProfile
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
def test_function():
result = fibonacci(30)
return result
# Lancement du profilage
cProfile.run('test_function()')
Le résultat du profilage contient des métriques importantes :
ncalls— nombre total d'appels de la fonctiontottime— temps d'exécution de la fonction sans les appels imbriquéspercall— temps moyen par appelcumtime— temps total incluant tous les appels imbriquésfilename:lineno(function)— emplacement de la fonction dans le code
Le module timeit pour des mesures ciblées
Pour mesurer le temps d'exécution de petits fragments de code, on utilise le module timeit :
import timeit
# Comparaison de différentes méthodes de création de liste
list_comprehension = timeit.timeit('[i*2 for i in range(1000)]', number=1000)
map_function = timeit.timeit('list(map(lambda x: x*2, range(1000)))', number=1000)
print(f"List comprehension : {list_comprehension:.6f} sec")
print(f"Fonction map : {map_function:.6f} sec")
Le module profile pour une analyse détaillée
Un profileur intégré alternatif, plus lent que cProfile mais fournissant des informations plus détaillées :
import profile
def complex_calculation():
data = []
for i in range(10000):
data.append(i ** 2)
return sum(data)
profile.run('complex_calculation()')
Outils de profilage externes
line_profiler — profilage ligne par ligne
Cet outil affiche le temps d'exécution de chaque ligne de code :
pip install line_profiler
@profile
def process_data():
data = []
for i in range(100000): # Cette ligne peut être un goulot d'étranglement
data.append(i * 2)
return sum(data)
Lancement du profilage ligne par ligne :
kernprof -l -v script.py