Eche un vistazo a timeit , el generador de perfiles de python y pycallgraph . También asegúrese de echar un vistazo al comentario a continuaciónnikicc
mencionando " SnakeViz ". Le brinda otra visualización de los datos de creación de perfiles que puede ser útil.
cronométralo
def test():
"""Stupid test function"""
lst = []
for i in range(100):
lst.append(i)
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
print(timeit.timeit("test()", globals=locals()))
Esencialmente, puede pasarle código Python como un parámetro de cadena, y se ejecutará en la cantidad de veces especificada e imprimirá el tiempo de ejecución. Los bits importantes de los documentos :
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)
Cree una Timer
instancia con la declaración dada, el
código de configuración y la función de temporizador y ejecute su timeit
método con
ejecuciones numéricas . El argumento global opcional especifica un espacio de nombres en el que ejecutar el código.
... y:
Timer.timeit(number=1000000)
Número de ejecuciones de
tiempo de la declaración principal. Esto ejecuta la instrucción de configuración una vez y luego devuelve el tiempo que lleva ejecutar la instrucción principal varias veces, medido en segundos como un valor flotante. El argumento es el número de veces que se recorre el ciclo, con un valor predeterminado de un millón. La declaración principal, la declaración de configuración y la función de temporizador que se utilizarán se pasan al constructor.
Nota:
De forma predeterminada, timeit
se apaga temporalmente garbage collection
durante el tiempo. La ventaja de este enfoque es que hace que los tiempos independientes sean más comparables. Esta desventaja es que GC puede ser un componente importante del desempeño de la función que se mide. Si es así, GC se puede volver a habilitar como la primera declaración en la cadena de configuración . Por ejemplo:
timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()
Perfilado
La creación de perfiles le dará una idea mucho más detallada sobre lo que está sucediendo. Aquí está el "ejemplo instantáneo" de los documentos oficiales :
import cProfile
import re
cProfile.run('re.compile("foo|bar")')
Que te dará:
197 function calls (192 primitive calls) in 0.002 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.001 0.001 <string>:1(<module>)
1 0.000 0.000 0.001 0.001 re.py:212(compile)
1 0.000 0.000 0.001 0.001 re.py:268(_compile)
1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset)
1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset)
4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction)
3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile)
Ambos módulos deberían darle una idea de dónde buscar los cuellos de botella.
Además, para familiarizarse con el resultado de profile
, eche un vistazo a esta publicación
pycallgraph
NOTA pycallgraph ha sido oficialmente abandonado desde febrero de 2018 . Sin embargo, en diciembre de 2020 todavía estaba funcionando en Python 3.6. Sin embargo, siempre que no haya cambios fundamentales en la forma en que Python expone la API de creación de perfiles, debería seguir siendo una herramienta útil.
Este módulo utiliza graphviz para crear gráficos de llamadas como los siguientes:

Puede ver fácilmente qué caminos se utilizaron más tiempo por color. Puede crearlos usando la API de pycallgraph o usando un script empaquetado:
pycallgraph graphviz -- ./mypythonscript.py
Sin embargo, la sobrecarga es bastante considerable. Por lo tanto, para procesos que ya se ejecutan durante mucho tiempo, la creación del gráfico puede llevar algún tiempo.
python -m cProfile -o results.prof myscript.py
. El archivo oputput puede ser muy bien presentado en un navegador por medio de un programa llamado SnakeViz usandosnakeviz results.prof