Есть ли статистический профайлер для python? Если нет, то как я могу написать? - PullRequest
17 голосов
/ 11 апреля 2011

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

Ответы [ 7 ]

13 голосов
/ 26 апреля 2012

Модуль statprof

pip install statprof (или easy_install statprof), затем использовать:

import statprof

statprof.start()
try:
    my_questionable_function()
finally:
    statprof.stop()
    statprof.display()

В модуле есть немного информации об этом блоге :

Почему это важно? В Python уже есть два встроенных профилировщика: lsprof и долгожданная горячая реплика. Проблема с lsprof состоит в том, что он отслеживает только вызовы функций. Если у вас есть несколько горячих циклов внутри функции, lsprof почти бесполезен для определения, какие из них действительно важны.

Несколько дней назад я попал точно в ситуацию, в которой lsprof дает сбой: он говорил мне, что у меня была горячая функция, но эта функция была мне незнакома, и достаточно долго, чтобы не было сразу видно, где проблема была.

После небольшой просьбы в Twitter и Google+ кто-то указал мне на statprof. Но была проблема: хотя он делал статистическую выборку (да!), Он отслеживал только первую строку функции при выборке (wtf !?). Поэтому я исправил это, просмотрел документацию, и теперь она полезна и не вводит в заблуждение. Вот пример его вывода, более точно определяющий местоположение ошибочной строки в этой горячей функции:

  %   cumulative      self          
 time    seconds   seconds  name    
 68.75      0.14      0.14  scmutil.py:546:revrange
  6.25      0.01      0.01  cmdutil.py:1006:walkchangerevs
  6.25      0.01      0.01  revlog.py:241:__init__
  [...blah blah blah...]
  0.00      0.01      0.00  util.py:237:__get__
---
Sample count: 16
Total time: 0.200000 seconds

Я загрузил statprof в индекс пакета Python, поэтому его установка почти тривиальна: «easy_install statprof», и вы уже в работе.

Поскольку код на github , пожалуйста, не стесняйтесь сообщать об ошибках и улучшениях. Наслаждайтесь!

5 голосов
/ 11 апреля 2011

Я могу подумать о паре нескольких способов сделать это:

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

    • На самом деле, вместо того, чтобы анализировать выходные данные, вы можете зарегистрировать подпрограмму postmortem (используя sys.excepthook), которая регистрирует трассировку стека. К сожалению, у Python нет возможности продолжить с того момента, когда произошло исключение, поэтому вы не можете возобновить выполнение после регистрации.
  • Чтобы фактически получить трассировку стека от работающей программы, вам потребуется , возможно, придется взломать реализацию. Поэтому, если вы действительно хотите это сделать, возможно, стоит потратить время на ознакомление с pypy , реализацией Python, написанной в основном на Python. Я понятия не имею, насколько удобно было бы делать это в pypy. Я предполагаю, что это не было бы особенно удобно, так как это включало бы введение хука практически в каждую инструкцию, что, я думаю, было бы чрезмерно неэффективным. Кроме того, я не думаю, что будет больше преимуществ по сравнению с первым вариантом, если только не требуется очень много времени, чтобы достичь состояния, в котором вы хотите начать выполнять трассировку стека.

  • Существует набор макросов для отладчика gdb, предназначенный для облегчения отладки самого Python. GDB может подключаться к внешнему процессу (в данном случае к экземпляру Python, который выполняет ваше приложение) и делать с ним что угодно. Кажется, что макрос pystack вернет вам стек Python в текущей точке выполнения. Я думаю, было бы довольно легко автоматизировать эту процедуру, так как вы можете (в худшем случае) просто ввести текст в gdb, используя expect или что-то еще.

3 голосов
/ 16 марта 2012

Python уже содержит все, что вам нужно, чтобы сделать то, что вы описали, не нужно взламывать переводчик.

Вам просто нужно использовать модуль traceback вместе с sys._current_frames() функция.Все, что вам нужно, это способ выгрузки необходимых вам трассировок на нужной частоте, например, с помощью сигналов UNIX или другого потока.

Чтобы быстро запустить ваш код, вы можете делать именно то, что делается в this commit :

  1. Скопируйте модуль threads.py из этого коммита или хотя бы функцию дампа трассировки стека (лицензия ZPL, очень либеральная):

  2. Подключите его к обработчику сигналов, скажем, SIGUSR1

Тогда вам просто нужнозапустите ваш код и «убейте» его с помощью SIGUSR1 так часто, как вам нужно.

Для случая, когда одна функция из одного потока время от времени «выбирается» одной и той же техникой, используя другой поток длявремя, я предлагаю анализировать код Products.LongRequestLogger и его тесты (разработанные вами по-настоящему, в то время как под управлением Nexedi ):

Является ли это правильным «статистическим» профилированием, ответ от Mike Dunlavey , на который ссылается intuited , убедительно доказывает, что это очень мощная техника «отладки производительности», и у меня есть личный опыт, который действительно помогает быстро увеличить реальные причины производительностивопросы.

2 голосов
/ 11 апреля 2011

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

В общем, это не простая проблема, но вы можете попробовать начать с GDB 7 и связанных инструментов анализа CPython.

1 голос
/ 05 мая 2019

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

Это снимок экрана с Austin TUI, терминальным приложением, которое обеспечивает вид сверхувсего, что происходит внутри запущенного приложения Python.Austin TUI

Это веб-приложение для веб-поиска в Остине, которое отображает график живого пламени собранных образцов.Вы можете настроить адрес, по которому приложение будет обслуживать приложение, которое затем позволяет выполнять удаленное профилирование.

enter image description here

1 голос
/ 23 августа 2018

Через семь лет после того, как вопрос был задан, в настоящее время для Python доступно несколько хороших статистических профилировщиков.Помимо vmprof, уже упомянутого Дмитрием Трофимовым в этом ответе, существуют также vprof и pyflame .Все они поддерживают графики пламени , так или иначе, давая вам хороший обзор того, где было потрачено время.

1 голос
/ 24 марта 2017

Существует кроссплатформенная выборочная (статистическая) программа Python, написанная на языке C, которая называется vmprof-python .Разработанный членами команды PyPy, он поддерживает PyPy, а также CPython.Он работает на Linux, Mac OSX и Windows.Он написан на C, поэтому имеет очень небольшие накладные расходы.Он профилирует код Python, а также нативные вызовы, сделанные из кода Python.Кроме того, он имеет очень полезную опцию для сбора статистики о строках выполнения внутри функций в дополнение к именам функций.Он также может профилировать использование памяти (отслеживая размер кучи).

Его можно вызвать из кода Python через API или из консоли.Существует веб-интерфейс для просмотра дампов профиля: vmprof.com , который также с открытым исходным кодом .

Кроме того, некоторые Python IDE (например, PyCharm) имеютинтеграция с ним, позволяющая запустить профилировщик и просмотреть результаты в редакторе.

...