varias una separar saltos salto print por lista lineas linea insertar hace escribir como agregar python profiling line-by-line

una - separar string por saltos de linea python



¿Cómo puedo perfilar el código python línea por línea? (3)

He estado usando cProfile para perfilar mi código, y ha estado funcionando genial. También uso gprof2dot.py para visualizar los resultados (lo hace un poco más claro).

Sin embargo, cProfile (y la mayoría de los demás analizadores de Python que he visto hasta ahora) parecen tener solo un perfil en el nivel de llamada de función. Esto causa confusión cuando se llaman ciertas funciones desde diferentes lugares. No tengo idea si la llamada n. ° 1 o la n. ° 2 ocupan la mayor parte del tiempo. Esto empeora cuando la función en cuestión tiene 6 niveles de profundidad, llamada desde 7 otros lugares.

Entonces mi pregunta es: ¿cómo obtengo un perfil línea por línea? En lugar de esto:

function #12, total time: 2.0s

Me gustaría ver algo como esto:

function #12 (called from somefile.py:102) 0.5s function #12 (called from main.py:12) 1.5s

cProfile muestra cuánto del tiempo total se "transfiere" al padre, pero nuevamente esta conexión se pierde cuando tienes un montón de capas y llamadas interconectadas.

Idealmente, me encantaría tener una GUI que analice los datos, y luego mostrarme mi archivo fuente con un tiempo total dado a cada línea. Algo como esto:

main.py: a = 1 # 0.0s result = func(a) # 0.4s c = 1000 # 0.0s result = func(c) # 5.0s

Luego, podré hacer clic en la segunda llamada "func (c)" para ver lo que está tomando tiempo en esa llamada, separada de la llamada "func (a)".

¿Tiene sentido? ¿Hay alguna biblioteca de creación de perfiles que recopile este tipo de información? ¿Hay alguna herramienta increíble que me he perdido? Cualquier comentario es apreciado. ¡¡Gracias!!


Creo que para eso está diseñado el profile_profiler de Robert Kern . Desde el enlace:

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

¡Espero que ayude!


PyVmMonitor tiene una vista en vivo que puede ayudarlo (puede conectarse a un programa en ejecución y obtener estadísticas de él).

Ver: http://www.pyvmmonitor.com/


También podría usar pprofile ( pypi ). Si desea perfilar toda la ejecución, no requiere modificación del código fuente. También puede perfilar un subconjunto de un programa más grande de dos maneras:

  • alternar perfiles cuando se llega a un punto específico en el código, como:

    import pprofile profiler = pprofile.Profile() with profiler: some_code # Process profile content: generate a cachegrind file and send it to user.

  • Alternar perfiles de forma asíncrona desde la pila de llamadas (requiere una forma de activar este código en una aplicación considerada, por ejemplo, un manejador de señal o un subproceso de trabajo disponible) mediante el uso de perfiles estadísticos:

    import pprofile profiler = pprofile.StatisticalProfile() statistical_profiler_thread = pprofile.StatisticalThread( profiler=profiler, ) with statistical_profiler_thread: sleep(n) # Likewise, process profile content

El formato de salida de anotación de código es muy parecido al perfilador de línea:

$ 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

Tenga en cuenta que, dado que pprofile no depende de la modificación del código, puede perfilar las declaraciones del módulo de nivel superior, lo que permite perfilar el tiempo de inicio del programa (cuánto tiempo lleva importar módulos, inicializar globales, ...).

Puede generar salida con formato cachegrind, por lo que puede usar kcachegrind para navegar fácilmente por resultados grandes.

Divulgación: soy un autor pprofile.