Как вы можете профилировать скрипт Python? - PullRequest
1123 голосов
/ 24 февраля 2009

Project Euler и другие конкурсы по кодированию часто имеют максимальное время для запуска или люди хвастаются тем, насколько быстро работает их конкретное решение. В случае с Python подходы иногда оказываются несколько хитрыми, то есть добавление временного кода к __main__.

Как правильно определить, сколько времени занимает запуск программы на Python?

Ответы [ 23 ]

1210 голосов
/ 24 февраля 2009

Python включает в себя профилировщик с именем cProfile . Он не только показывает общее время выполнения, но и время каждой функции в отдельности и сообщает, сколько раз была вызвана каждая функция, что позволяет легко определить, где вы должны выполнить оптимизацию.

Вы можете позвонить из своего кода или из интерпретатора, например:

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

Еще полезнее, вы можете вызвать cProfile при запуске скрипта:

python -m cProfile myscript.py

Чтобы сделать это еще проще, я создал небольшой командный файл с именем 'profile.bat':

python -m cProfile %1

Так что все, что мне нужно сделать, это запустить:

profile euler048.py

И я получаю это:

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}

РЕДАКТИРОВАТЬ: Обновлена ​​ссылка на хороший видео-ресурс из PyCon 2013 под названием Профилирование Python
Также через YouTube .

387 голосов
/ 06 августа 2012

Некоторое время назад я сделал pycallgraph, который генерирует визуализацию из вашего кода Python. Редактировать: Я обновил пример для работы с 3.3, последней версией на момент написания.

После pip install pycallgraph и установки GraphViz вы можете запустить его из командной строки:

pycallgraph graphviz -- ./mypythonscript.py

Или вы можете профилировать отдельные части своего кода:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

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

Любой из них создаст файл pycallgraph.png, подобный изображению ниже:

enter image description here

188 голосов
/ 17 декабря 2009

Стоит отметить, что использование профилировщика работает (по умолчанию) только в основном потоке, и вы не получите никакой информации из других потоков, если будете их использовать. Это может быть немного затруднительно, поскольку в документации .

об этом совершенно не упоминается.

Если вы также хотите профилировать темы, вам нужно взглянуть на threading.setprofile() функцию в документации.

Вы также можете создать собственный подкласс threading.Thread, чтобы сделать это:

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,))

и используйте этот ProfiledThread класс вместо стандартного. Это может дать вам больше гибкости, но я не уверен, что оно того стоит, особенно если вы используете сторонний код, который не будет использовать ваш класс.

136 голосов
/ 08 октября 2011

Python Wiki - отличная страница для профилирования ресурсов: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

как и документы по питону: http://docs.python.org/library/profile.html

как показывает Крис Лоулор cProfile - отличный инструмент, который можно легко использовать для печати на экране:

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

или в файл:

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

PS> Если вы используете Ubuntu, обязательно установите профиль python

sudo apt-get install python-profiler 

Если вы выводите в файл, вы можете получить хорошую визуализацию, используя следующие инструменты

PyCallGraph: инструмент для создания изображений графа вызовов
установить:

 sudo pip install pycallgraph

пробег:

 pycallgraph mine.py args

вид:

 gimp pycallgraph.png

Вы можете использовать все, что угодно, чтобы просмотреть файл png, я использовал gimp
К сожалению, я часто получаю

точка: график слишком велик для растровых изображений cairo-renderer. Масштабирование по 0,257079, чтобы соответствовать

, что делает мои изображения необычно маленькими. Поэтому я обычно создаю SVG-файлы:

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

PS> не забудьте установить graphviz (который предоставляет программу dot):

sudo pip install graphviz

Альтернативный график с использованием gprof2dot через @maxy / @quodlibetor:

sudo pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg
127 голосов
/ 12 декабря 2012

@ Комментарий Макси этот ответ выручил меня настолько, что я думаю, что он заслуживает своего собственного ответа: у меня уже были сгенерированные cProfile файлы .pstats, и я не хотел перезапускать вещи с pycallgraph , поэтому я использовал gprof2dot и получил довольно 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

и БЛАМ!

Он использует точку (то же самое, что и pycallgraph), поэтому вывод выглядит аналогично. У меня создается впечатление, что gprof2dot теряет меньше информации:

gprof2dot example output

57 голосов
/ 25 мая 2016

Я столкнулся с удобным инструментом под названием SnakeViz при исследовании этой темы. SnakeViz - это веб-инструмент для визуализации профилирования. Это очень легко установить и использовать. Обычно я использую его, чтобы сгенерировать файл статистики с %prun, а затем выполнить анализ в SnakeViz.

Основной используемый метод, а именно Диаграмма солнечных лучей , как показано ниже, в которой иерархия вызовов функций организована в виде слоев дуг и информации о времени, закодированных в их угловых ширинах.

Самое лучшее, что вы можете взаимодействовать с графиком. Например, чтобы увеличить масштаб, можно щелкнуть по дуге, и дуга и ее потомки будут увеличены до новых солнечных лучей, чтобы отобразить больше деталей.

enter image description here

43 голосов
/ 11 мая 2016

Я думаю, что cProfile отлично подходит для профилирования, а kcachegrind отлично подходит для визуализации результатов. pyprof2calltree между ними обрабатывает преобразование файла.

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

Чтобы установить необходимые инструменты (как минимум, в Ubuntu):

apt-get install kcachegrind
pip install pyprof2calltree

Результат:

Screenshot of the result

39 голосов
/ 22 февраля 2015

Также стоит упомянуть программу просмотра дампа cProfile с графическим интерфейсом RunSnakeRun . Это позволяет вам сортировать и выбирать, тем самым увеличивая соответствующие части программы. Размеры прямоугольников на картинке пропорциональны затраченному времени. Если вы наведите курсор мыши на прямоугольник, он выделит этот вызов в таблице и повсюду на карте. Когда вы дважды щелкаете на прямоугольнике, он увеличивает эту часть. Он покажет вам, кто вызывает эту часть и что эта часть вызывает.

Описательная информация очень полезна. Он показывает вам код для этого бита, который может быть полезен, когда вы имеете дело со встроенными вызовами библиотеки. Он говорит вам, какой файл и в какой строке найти код.

Также хочу указать на то, что ОП сказал «профилирование», но, похоже, он имел в виду «выбор времени». Имейте в виду, что программы будут работать медленнее при профилировании.

enter image description here

31 голосов
/ 20 октября 2011

Хорошим модулем профилирования является line_profiler (вызывается с помощью скрипта kernprof.py). Его можно скачать здесь .

Насколько я понимаю, cProfile предоставляет информацию только об общем времени, потраченном на каждую функцию. Таким образом, отдельные строки кода не рассчитаны. Это проблема научных вычислений, поскольку часто одна строка может занимать много времени. Кроме того, насколько я помню, cProfile не улавливал время, которое я проводил, скажем, в numpy.dot.

30 голосов
/ 08 марта 2018

Самый простой и Самый быстрый способ узнать, куда все время идет.

1. pip install snakeviz

2. python -m cProfile -o temp.dat <PROGRAM>.py

3. snakeviz temp.dat

Рисует круговую диаграмму в браузере. Самая большая часть - это проблемная функция. Очень просто.

...