Pregunta ¿Cómo se puede perfilar un script?


El proyecto Euler y otros concursos de codificación a menudo tienen un tiempo máximo para correr o las personas se jactan de lo rápido que se ejecuta su solución particular. Con Python, a veces los enfoques son un poco dudosos, es decir, agregando código de tiempo a __main__.

¿Cuál es una buena forma de hacer un perfil de cuánto tarda un programa de Python en ejecutarse?


973
2018-02-24 16:01


origen


Respuestas:


Python incluye un generador de perfiles llamado cProfile. No solo proporciona el tiempo de ejecución total, sino también cada función por separado, y le indica cuántas veces se llamó a cada función, lo que facilita la determinación de dónde debe realizar las optimizaciones.

Puede llamarlo desde su código o desde el intérprete, así:

import cProfile
cProfile.run('foo()')

Aún más útil, puede invocar el cProfile cuando se ejecuta un script:

python -m cProfile myscript.py

Para hacerlo aún más fácil, hice un pequeño archivo por lotes llamado 'profile.bat':

python -m cProfile %1

Entonces todo lo que tengo que hacer es correr:

profile euler048.py

Y entiendo esto:

1007 function calls in 0.061 CPU seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.061    0.061 <string>:1(<module>)
 1000    0.051    0.000    0.051    0.000 euler048.py:2(<lambda>)
    1    0.005    0.005    0.061    0.061 euler048.py:2(<module>)
    1    0.000    0.000    0.061    0.061 {execfile}
    1    0.002    0.002    0.053    0.053 {map}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}
    1    0.000    0.000    0.000    0.000 {range}
    1    0.003    0.003    0.003    0.003 {sum}

EDITAR: Enlace actualizado a un buen recurso de video de PyCon 2013 titulado Perfiles de Python
También a través de YouTube.


1073
2018-02-24 16:01



Hace un tiempo hice pycallgraph que genera una visualización desde tu código Python. Editar: Actualicé el ejemplo para trabajar con la última versión.

Después de pip install pycallgraph e instalando GraphViz puedes ejecutarlo desde la línea de comando:

pycallgraph graphviz -- ./mypythonscript.py

O bien, puede perfilar partes particulares de su código:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

Cualquiera de estos generará un pycallgraph.png archivo similar a la imagen a continuación:

enter image description here


349
2017-08-06 05:37



Vale la pena señalar que el uso del generador de perfiles solo funciona (de forma predeterminada) en el hilo principal, y no obtendrá información de otros hilos si los usa. Esto puede ser un poco impreciso ya que no se menciona por completo en el documentación del perfilador.

Si también desea perfiles de hilos, querrá mirar el threading.setprofile() función en los documentos.

También puedes crear tu propio threading.Thread subclase para hacerlo:

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

y usa eso ProfiledThread clase en lugar de la estándar. Puede darte más flexibilidad, pero no estoy seguro de que valga la pena, especialmente si estás usando un código de un tercero que no usaría tu clase.


167
2017-12-17 16:30



La wiki de python es una gran página para crear perfiles de recursos: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

como es el Python Docs: http://docs.python.org/library/profile.html

como lo muestra Chris Lawlor cProfile es una gran herramienta y se puede usar fácilmente para imprimir en la pantalla:

python -m cProfile -s time mine.py <args>

o para archivar:

python -m cProfile -o output.file mine.py <args>

PD> Si está utilizando Ubuntu, asegúrese de instalar Python-profile

sudo apt-get install python-profiler 

Si imprime en un archivo, puede obtener agradables visualizaciones usando las siguientes herramientas

PyCallGraph: una herramienta para crear imágenes de gráficos de llamadas
  instalar:

 sudo pip install pycallgraph

correr:

 pycallgraph mine.py args

ver:

 gimp pycallgraph.png

Puedes usar lo que quieras para ver el archivo png, utilicé gimp
Lamentablemente, a menudo

punto: el gráfico es demasiado grande para los mapas de bits de renderizado de cairo. Escalado por 0.257079 para adaptarse

que hace que mis imágenes sean indescriptiblemente pequeñas. Así que generalmente creo archivos svg:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PD> asegúrese de instalar graphviz (que proporciona el programa de puntos):

sudo pip install graphviz

Gráficas alternativas usando gprof2dot a través de @maxy / @quodlibetor:

sudo pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

126
2017-10-08 00:04



Comentario de @Maxy en esta respuesta me ayudó lo suficiente como para pensar que merece su propia respuesta: ya tenía archivos .pstats generados por cProfile y no quería volver a ejecutar cosas con pycallgraph, así que usé gprof2dot, y consiguió bastante svgs:

$ sudo apt-get install graphviz
$ git clone https://github.com/jrfonseca/gprof2dot
$ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin
$ cd $PROJECT_DIR
$ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg

y BLAM!

Utiliza punto (lo mismo que utiliza pictograma) por lo que el resultado es similar. Me da la impresión de que gprof2dot pierde menos información:

gprof2dot example output


113
2017-12-11 23:16



Me encontré con una herramienta útil llamada SnakeViz cuando investiga este tema. SnakeViz es una herramienta de visualización de perfiles basada en la web. Es muy fácil de instalar y usar. La forma habitual en que lo uso es generar un archivo de estadísticas con %prun y luego hacer el análisis en SnakeViz.

La principal técnica utilizada es Gráfico de Sunburst como se muestra a continuación, en el cual la jerarquía de llamadas a funciones está dispuesta como capas de arcos e información de tiempo codificada en sus anchuras angulares.

Lo mejor es que puedes interactuar con la tabla. Por ejemplo, para acercar uno puede hacer clic en un arco, y el arco y sus descendientes se ampliarán como un nuevo resplandor solar para mostrar más detalles.

enter image description here


41
2018-05-25 08:06



También vale la pena mencionar es el GUI cProfile dump viewer RunSnakeRun. Le permite ordenar y seleccionar, haciendo un acercamiento de las partes relevantes del programa. Los tamaños de los rectángulos en la imagen son proporcionales al tiempo empleado. Si pasa el mouse sobre un rectángulo, resalta esa llamada en la tabla y en todas partes del mapa. Cuando hace doble clic en un rectángulo, amplía esa porción. Le mostrará quién llama a esa parte y a qué llama esa parte.

La información descriptiva es muy útil. Le muestra el código para ese bit que puede ser útil cuando se trata de llamadas a bibliotecas integradas. Le dice qué archivo y qué línea encontrar el código.

También quiero señalar que el OP dijo 'perfil', pero parece que quiso decir 'timing'. Tenga en cuenta que los programas se ejecutarán más lentamente cuando se perfilen.

enter image description here


33
2018-02-22 16:18



Creo que cProfile es ideal para perfilar, mientras kcachegrind es ideal para visualizar los resultados. los pyprof2calltree entre maneja la conversión de archivos.

python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree

Para instalar las herramientas necesarias (en Ubuntu, al menos):

apt-get install kcachegrind
pip install pyprof2calltree

El resultado:

Screenshot of the result


29
2018-05-11 08:32



pprofile

line_profiler (ya presentado aquí) también inspirado pprofile, que se describe como:

Line-granularity, thread-aware deterministic y statistic pure-python   perfilador

Proporciona granularidad de línea como line_profiler, es Python puro, se puede usar como un comando independiente o un módulo, e incluso puede generar archivos en formato callgrind que se pueden analizar fácilmente con [k|q]cachegrind.

vprof

También hay vprof, un paquete de Python descrito como:

[...] proporcionando visualizaciones ricas e interactivas para diversas características del programa Python, como el tiempo de ejecución y el uso de la memoria.

heatmap


28
2018-03-02 11:36



Un buen módulo de creación de perfiles es line_profiler (llamado usando el script kernprof.py). Se puede descargar aquí.

Tengo entendido que cProfile solo brinda información sobre el tiempo total dedicado a cada función. Por lo tanto, las líneas de código individuales no están cronometradas. Este es un problema en la informática científica ya que a menudo una sola línea puede llevar mucho tiempo. Además, como recuerdo, cProfile no captó el tiempo que estaba gastando en decir numpy.dot.


27
2017-10-20 16:05