Gráficos de llama de CPU para Python
performance linux-kernel (1)
Tal vez puedas probar sys.setprofile
, que es el núcleo para el profile
python estándar y cProfile
. Este método establece un enlace a los eventos "llamar" y "devolver" de cada función, incluidas las funciones de C-API.
La función de perfil del sistema se llama de manera similar a la función de rastreo del sistema (ver settrace ()), pero no se llama para cada línea de código ejecutada (solo en llamada y devolución, pero el evento de devolución se informa incluso cuando se ha producido una excepción conjunto).
A continuación se muestra un ejemplo de trabajo:
from time import clock
t0 = clock()
def getFun(frame):
code = frame.f_code
return code.co_name+'' in ''+code.co_filename+'':''+str(code.co_firstlineno)
def trace_dispatch(frame, event, arg):
if event in [ "c_call" , ''call'', ''return'', ''c_return'']:
t = int((clock()-t0)*1000)
f = frame
stack=[]
while(f):
stack.insert( 0,getFun(f) )
f = f.f_back
print event, ''/t'', ''; ''.join(stack), ''; '', t
import sys
sys.setprofile(trace_dispatch)
try:
execfile(''test.py'')
finally:
sys.setprofile(None)
Test.py
def f(x):
return x+1
def main(x):
return f(x)
main(10)
Esto se imprimirá
c_call 0
call <module> in test.py:2 ; 1
call <module> in test.py:2; main in test.py:5 ; 1
call <module> in test.py:2; main in test.py:5; f in test.py:2 ; 5
return <module> in test.py:2; main in test.py:5; f in test.py:2 ; 8
return <module> in test.py:2; main in test.py:5 ; 11
return <module> in test.py:2 ; 14
c_return 18
c_call 21
Vea una función de creación de perfiles más completa aquí .
C stack en python
No puede acceder a la pila C dentro del intérprete de Python. Es necesario usar un depurador o generador de perfiles que admita C / C ++. Yo recomendaría gdb python .
Los gráficos de llama de la CPU de Brendan Gregg son una forma de visualizar el uso de la CPU durante un período de tiempo basado en las pilas de llamadas.
Su proyecto FlameGraph github proporciona una forma independiente del lenguaje para trazar estos gráficos:
Para cada idioma, FlameGraph requiere una forma de proporcionar la entrada de pila en forma de líneas como esta:
grandparent_func;parent_func;func 42
Esto significa que el programa instrumentado se observó ejecutando la función func
, donde se llamó desde parent_func
, a su vez llamado desde la función de nivel superior grandparent_func
. Dice que la pila de llamadas se observó 42 veces.
¿Cómo puedo recopilar información de la pila de los programas de Python y proporcionarla a FlameGraph?
Para puntos de bonificación: ¿cómo se puede extender para que se muestren tanto la pila de C como la de Python, o incluso hasta el kernel en Linux (de forma similar a algunos de los gráficos de llamas de Java y node.js en el sitio web de Brendan)?