J'utilise cProfile pour profiler mon code, et cela fonctionne très bien. J'utilise également gprof2dot.py pour visualiser les résultats (cela est un peu plus clair).
Cependant, cProfile (et la plupart des autres Python profileurs que j'ai vus jusqu'à présent) ne semblent profiler qu'au niveau de l'appel de fonction. Cela crée de la confusion lorsque certaines fonctions sont appelées à partir de différents endroits - j'ai aucune idée si l'appel n ° 1 ou l'appel n ° 2 prend la majorité du temps, ce qui est encore pire lorsque la fonction en question a six niveaux de profondeur, appelés depuis sept autres endroits.
Comment obtenir un profilage ligne par ligne?
Au lieu de cela:
function #12, total time: 2.0s
J'aimerais voir quelque chose comme ça:
function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s
cProfile montre combien de temps total "transfère" au parent, mais encore une fois cette connexion est perdue lorsque vous avez un tas de couches et d'appels interconnectés.
Idéalement, j'aimerais avoir une interface graphique qui analyserait les données, puis me montrerait mon fichier source avec un temps total donné à chaque ligne. Quelque chose comme ça:
main.py:
a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s
Ensuite, je serais en mesure de cliquer sur le deuxième appel "func (c)" pour voir ce qui prend du temps dans cet appel, distinct de l'appel "func (a)".
Cela a-t-il du sens? Existe-t-il une bibliothèque de profilage qui collecte ce type d'informations? Y a-t-il un outil génial que j'ai manqué?
Je crois que c'est à cela que line_profiler de Robert Kern est destiné. Depuis le lien:
File: pystone.py
Function: Proc2 at line 149
Total time: 0.606656 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
149 @profile
150 def Proc2(IntParIO):
151 50000 82003 1.6 13.5 IntLoc = IntParIO + 10
152 50000 63162 1.3 10.4 while 1:
153 50000 69065 1.4 11.4 if Char1Glob == 'A':
154 50000 66354 1.3 10.9 IntLoc = IntLoc - 1
155 50000 67263 1.3 11.1 IntParIO = IntLoc - IntGlob
156 50000 65494 1.3 10.8 EnumLoc = Ident1
157 50000 68001 1.4 11.2 if EnumLoc == Ident1:
158 50000 63739 1.3 10.5 break
159 50000 61575 1.2 10.1 return IntParIO
J'espère que ça t'as aidé!
Vous pouvez également utiliser pprofile ( pypi ). Si vous souhaitez profiler l'exécution entière, elle ne nécessite pas de modification du code source. Vous pouvez également profiler un sous-ensemble d'un programme plus vaste de deux manières:
basculer le profilage lorsque vous atteignez un point spécifique dans le code, tel que:
import pprofile
profiler = pprofile.Profile()
with profiler:
some_code
# Process profile content: generate a cachegrind file and send it to user.
basculer le profilage de manière asynchrone à partir de la pile d'appels (nécessite un moyen de déclencher ce code dans l'application considérée, par exemple un gestionnaire de signal ou un thread de travail disponible) en utilisant le profilage statistique:
import pprofile
profiler = pprofile.StatisticalProfile()
statistical_profiler_thread = pprofile.StatisticalThread(
profiler=profiler,
)
with statistical_profiler_thread:
sleep(n)
# Likewise, process profile content
Le format de sortie des annotations de code ressemble beaucoup au profileur de lignes:
$ pprofile --threads 0 demo/threads.py
Command line: ['demo/threads.py']
Total duration: 1.00573s
File: demo/threads.py
File duration: 1.00168s (99.60%)
Line #| Hits| Time| Time per hit| %|Source code
------+----------+-------------+-------------+-------+-----------
1| 2| 3.21865e-05| 1.60933e-05| 0.00%|import threading
2| 1| 5.96046e-06| 5.96046e-06| 0.00%|import time
3| 0| 0| 0| 0.00%|
4| 2| 1.5974e-05| 7.98702e-06| 0.00%|def func():
5| 1| 1.00111| 1.00111| 99.54%| time.sleep(1)
6| 0| 0| 0| 0.00%|
7| 2| 2.00272e-05| 1.00136e-05| 0.00%|def func2():
8| 1| 1.69277e-05| 1.69277e-05| 0.00%| pass
9| 0| 0| 0| 0.00%|
10| 1| 1.81198e-05| 1.81198e-05| 0.00%|t1 = threading.Thread(target=func)
(call)| 1| 0.000610828| 0.000610828| 0.06%|# /usr/lib/python2.7/threading.py:436 __init__
11| 1| 1.52588e-05| 1.52588e-05| 0.00%|t2 = threading.Thread(target=func)
(call)| 1| 0.000438929| 0.000438929| 0.04%|# /usr/lib/python2.7/threading.py:436 __init__
12| 1| 4.79221e-05| 4.79221e-05| 0.00%|t1.start()
(call)| 1| 0.000843048| 0.000843048| 0.08%|# /usr/lib/python2.7/threading.py:485 start
13| 1| 6.48499e-05| 6.48499e-05| 0.01%|t2.start()
(call)| 1| 0.00115609| 0.00115609| 0.11%|# /usr/lib/python2.7/threading.py:485 start
14| 1| 0.000205994| 0.000205994| 0.02%|(func(), func2())
(call)| 1| 1.00112| 1.00112| 99.54%|# demo/threads.py:4 func
(call)| 1| 3.09944e-05| 3.09944e-05| 0.00%|# demo/threads.py:7 func2
15| 1| 7.62939e-05| 7.62939e-05| 0.01%|t1.join()
(call)| 1| 0.000423908| 0.000423908| 0.04%|# /usr/lib/python2.7/threading.py:653 join
16| 1| 5.26905e-05| 5.26905e-05| 0.01%|t2.join()
(call)| 1| 0.000320196| 0.000320196| 0.03%|# /usr/lib/python2.7/threading.py:653 join
Notez que parce que pprofile ne repose pas sur la modification de code, il peut profiler les instructions de module de niveau supérieur, ce qui permet de profiler le temps de démarrage du programme (combien de temps il faut pour importer des modules, initialiser des globaux, ...).
Il peut générer une sortie au format cachegrind, vous pouvez donc utiliser kcachegrind pour parcourir facilement les grands résultats.
Divulgation: je suis l'auteur du profil.
PyVmMonitor a une vue en direct qui peut vous y aider (vous pouvez vous connecter à un programme en cours d'exécution et en obtenir des statistiques).
Vous pouvez utiliser l'aide de line_profiler package pour cela
1. Installez d'abord le paquet:
pip install line_profiler
2. Utilisez la commande magique pour charger le paquet dans votre environnement python/notebook
%load_ext line_profiler
. Si vous souhaitez profiler les codes d'une fonction,
procédez comme suit:% lprun -f nom_fonction appel_fonction
%lprun -f function_defined_by_you function_defined_by_you(arg1, arg2)
VOUS OBTIENDREZ UNE SORTIE FORMATÉE AVEC TOUS LES DÉTAILS SI VOUS SUIVEZ LES ÉTAPES CI-DESSUS