Как вы можете профилировать сценарий?

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

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

вопрос задан 24.02.2009
Chris Lawlor
23829 репутация

23 ответов


  • 1104 рейтинг

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

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

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

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

    python -m cProfile myscript.py
    

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

    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 :1()
     1000    0.051    0.000    0.051    0.000 euler048.py:2()
        1    0.005    0.005    0.061    0.061 euler048.py:2()
        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 Profiling
    Также через YouTube .

    ответ дан Chris Lawlor, с репутацией 23829, 24.02.2009
  • 352 рейтинг

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

    После 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

    ответ дан Gerald Kaszuba, с репутацией 19881, 6.08.2012
  • 172 рейтинг

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

    Если вы также хотите профилировать потоки, вам нужно посмотреть на функцию 3058373535 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 вместо стандартного. Это может дать вам больше гибкости, но я не уверен, что оно того стоит, особенно если вы используете сторонний код, который не будет использовать ваш класс.

    ответ дан Joe Shaw, с репутацией 13310, 17.12.2009
  • 127 рейтинг

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

    как и документы по питону: http: // docs. питон. орг / библиотека / профиль. HTML

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

    python -m cProfile -s time mine.py 
    

    или в файл:

    python -m cProfile -o output.file mine.py 
    

    PS & gt; Если вы используете Ubuntu, обязательно установите python-profile

    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 
    

    PS & gt; не забудьте установить 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
    
    ответ дан brent.payne, с репутацией 2633, 8.10.2011
  • 115 рейтинг

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

    ответ дан quodlibetor, с репутацией 4800, 11.12.2012
  • 43 рейтинг

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

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

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

    enter image description here

    ответ дан zaxliu, с репутацией 1345, 25.05.2016
  • 33 рейтинг

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

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

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

    enter image description here

    ответ дан Pete, с репутацией 7866, 22.02.2015
  • 32 рейтинг

    Я думаю, что 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

    ответ дан Federico, с репутацией 613, 11.05.2016
  • 28 рейтинг

    профиль

    line_profiler (уже представлен здесь) также вдохновил pprofile , который описывается как:

    Линейная гранулярность, потоково-детерминированный и статистический чистый Python профилировщик

    Он обеспечивает линейную гранулярность, поскольку line_profiler, является чистым Python, может использоваться в качестве отдельной команды или модуля и может даже генерировать файлы в формате callgrind, которые могут быть легко проанализированы с помощью [k|q]cachegrind.

    vprof

    Существует также vprof , пакет Python, описанный как:

    [. , , ] предоставление богатых и интерактивных визуализаций для различных характеристик программы Python, таких как время работы и использование памяти.

    heatmap

    ответ дан BenC, с репутацией 6348, 2.03.2015
  • 27 рейтинг

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

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

    ответ дан Ian Langmore, с репутацией 1104, 20.10.2011
  • 16 рейтинг

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

    1. pip install snakeviz
    
    2. python -m cProfile -o temp.dat .py
    
    3. snakeviz temp.dat
    

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

    ответ дан CodeCabbie, с репутацией 649, 8.03.2018
  • 11 рейтинг

    После ответа Джо Шоу о том, что многопоточный код не работает должным образом, я понял, что метод runcall в cProfile просто выполняет вызовы self.enable() и self.disable() вокруг вызова профилированной функции, поэтому вы можете просто сделать это самостоятельно и получить любой код Вы хотите промежуточный с минимальным вмешательством в существующий код.

    ответ дан PypeBros, с репутацией 1845, 9.11.2011
  • 10 рейтинг

    Есть много хороших ответов, но они либо используют командную строку, либо какую-то внешнюю программу для профилирования и / или сортировки результатов.

    Я действительно упустил какой-то способ, которым я мог бы использовать в своей IDE (eclipse-PyDev), не касаясь командной строки и не устанавливая что-либо. Так и здесь.

    Профилирование без командной строки

    def count():
        from math import sqrt
        for x in range(10**5):
            sqrt(x)
    
    if __name__ == '__main__':
        import cProfile, pstats
        cProfile.run("count()", "{}.profile".format(__file__))
        s = pstats.Stats("{}.profile".format(__file__))
        s.strip_dirs()
        s.sort_stats("time").print_stats(10)
    

    См. docs или другие ответы для получения дополнительной информации.

    ответ дан David Mašek, с репутацией 699, 21.08.2015
  • 9 рейтинг

    cProfile отлично подходит для быстрого профилирования, но большую часть времени он заканчивался для меня ошибками. Функция runctx решает эту проблему, правильно инициализируя окружение и переменные, надеюсь, это может кому-нибудь пригодиться:

    import cProfile
    cProfile.runctx('foo()', None, locals())
    
    ответ дан Datageek, с репутацией 13379, 30.03.2015
  • 6 рейтинг

    Мой способ - использовать yappi ( https: // code. Google. com / p / yappi / ). Это особенно полезно в сочетании с сервером RPC, где (даже только для отладки) вы регистрируете метод для запуска, остановки и печати информации профилирования, e. г. таким образом:

    @staticmethod
    def startProfiler():
        yappi.start()
    
    @staticmethod
    def stopProfiler():
        yappi.stop()
    
    @staticmethod
    def printProfiler():
        stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20)
        statPrint = '\n'
        namesArr = [len(str(stat[0])) for stat in stats.func_stats]
        log.debug("namesArr %s", str(namesArr))
        maxNameLen = max(namesArr)
        log.debug("maxNameLen: %s", maxNameLen)
    
        for stat in stats.func_stats:
            nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))]
            log.debug('nameAppendSpaces: %s', nameAppendSpaces)
            blankSpace = ''
            for space in nameAppendSpaces:
                blankSpace += space
    
            log.debug("adding spaces: %s", len(nameAppendSpaces))
            statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str(
                round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n"
    
        log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub")
        log.log(1000, statPrint)
    

    Затем, когда ваша программа заработает, вы можете в любой момент запустить профилировщик, вызвав метод RPC startProfiler и выгрузив информацию о профилировании в файл журнала, вызвав printProfiler (или изменив метод rpc, чтобы вернуть его вызывающей стороне) и получить такой вывод:

    2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
    name                                                                                                                                      ncall     ttot    tsub
    2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
    C:\Python27\lib\sched.py.run:80                                                                                                           22        0.11    0.05
    M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293                                                22        0.11    0.0
    M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515                                                    22        0.11    0.0
    M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66                                       1         0.0     0.0
    C:\Python27\lib\BaseHTTPServer.py.date_time_string:464                                                                                    1         0.0     0.0
    c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243     4         0.0     0.0
    C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537                                                                          1         0.0     0.0
    c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4         0.0     0.0
    .__new__:8                                                                                                                        220       0.0     0.0
    C:\Python27\lib\socket.py.close:276                                                                                                       4         0.0     0.0
    C:\Python27\lib\threading.py.__init__:558                                                                                                 1         0.0     0.0
    .__new__:8                                                                                                                        4         0.0     0.0
    C:\Python27\lib\threading.py.notify:372                                                                                                   1         0.0     0.0
    C:\Python27\lib\rfc822.py.getheader:285                                                                                                   4         0.0     0.0
    C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301                                                                                  1         0.0     0.0
    C:\Python27\lib\xmlrpclib.py.end:816                                                                                                      3         0.0     0.0
    C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467                                                                                         1         0.0     0.0
    C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460                                                                               1         0.0     0.0
    C:\Python27\lib\SocketServer.py.close_request:475                                                                                         1         0.0     0.0
    c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066               4         0.0     0.0 
    

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

    ответ дан Mr. Girgitt, с репутацией 1738, 19.02.2014
  • 3 рейтинг

    Новый инструмент для обработки профилирования в Python - это PyVmMonitor: http: // www. pyvmmonitor. com /

    У этого есть некоторые уникальные особенности, такие как

    • Присоединение профилировщика к запущенной (CPython) программе
    • Профилирование по требованию с интеграцией Yappi
    • Профиль на другой машине
    • Поддержка нескольких процессов (multiprocessing, django. , , )
    • Оперативная выборка / просмотр ЦП (с выбором диапазона времени)
    • Детерминированное профилирование через интеграцию cProfile / профиля
    • Анализ существующих результатов PStats
    • Открытые DOT файлы
    • Программный доступ к API
    • Группировка образцов по методу или линии
    • PyDev интеграция
    • PyCharm интеграция

    Примечание: он коммерческий, но бесплатный для открытого исходного кода.

    ответ дан Fabio Zadrozny, с репутацией 20831, 28.04.2015
  • 3 рейтинг

    Недавно я создал тунца для визуализации Python runtime и профилей импорта; это может быть полезно здесь.

    enter image description here

    Установить с

    pip3 install tuna
    

    Создать профиль времени выполнения

    python -mcProfile -o program.prof yourfile.py
    

    или профиль импорта (Python 3. 7+ требуется)

    python -X importprofile yourfile.py 2> import.log
    

    Тогда просто запустите тунца на файл

    tuna program.prof
    
    ответ дан Nico Schlömer, с репутацией 11152, 4.08.2018
  • 3 рейтинг

    Вы когда-нибудь хотели знать, что, черт возьми, делает этот скрипт Python? Введите Осмотрите Shell. Inspect Shell позволяет печатать / изменять глобальные переменные и запускать функционирует без прерывания работающего скрипта. Теперь с автозаполнение и история команд (только в Linux).

    Inspect Shell - не отладчик в стиле pdb.

    https: // github. com / amoffat / Inspect-Shell

    Вы можете использовать это (и ваши наручные часы).

    ответ дан Colonel Panic, с репутацией 77755, 13.10.2012
  • 3 рейтинг

    Для добавления на https: // stackoverflow. com / a / 582337/1070617 ,

    Я написал этот модуль, который позволяет вам использовать cProfile и легко просматривать его вывод. Подробнее здесь: https: // github. com / ymichael / cprofilev

    $ python -m cprofilev /your/python/program
    # Go to http://localhost:4000 to view collected statistics.
    

    См. Также: http: // ymichael. ком / 2014/03/08 / профилирование-питон-с-Cprofile. html о том, как разобраться в собранной статистике.

    ответ дан michael, с репутацией 31, 21.03.2015
  • 1 рейтинг

    Это будет зависеть от того, что вы хотите видеть из профилирования. Простое время Метрики могут быть даны (Bash).

    time python python_prog.py
    

    Даже '/ usr / bin / time' может выводить подробные метрики, используя флаг --verbose.

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

    Если говорить о более детальных показателях, таких как производительность, время - не единственная метрика. Вы можете беспокоиться о памяти, потоках и т. Д.
    Варианты профилирования:
    1. line_profiler - это другой профилировщик, используемый для построчного поиска метрик синхронизации.
    2. memory_profiler - это инструмент для профилирования использования памяти.
    3. heapy (из проекта Guppy) Профиль использования объектов в куче.

    Вот некоторые из них, которые я обычно использую. Но если вы хотите узнать больше, попробуйте прочитать эту книгу Это очень хорошая книга о том, как начать с производительности. Вы можете перейти к более сложным темам об использовании Python, скомпилированных в Cython и JIT (Just-in-time).

    ответ дан VishalMishra, с репутацией 11, 19.04.2017
  • 1 рейтинг

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

    Версия в pypi немного устарела, поэтому можно установить ее с pip, указав репозиторий git :

    pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01
    

    Вы можете запустить его так:

    import statprof
    
    with statprof.profile():
        my_questionable_function()
    

    См. Также https: // stackoverflow. com / a / 10333592/320036

    ответ дан z0r, с репутацией 4575, 11.02.2016
  • 0 рейтинг

    Когда я не root на сервере, я использую lsprofcalltree. py и запустите мою программу так:

    python lsprofcalltree.py -o callgrind.1 test.py
    

    Затем я могу открыть отчет с помощью любого callgrind-совместимого программного обеспечения, например, qcachegrind

    ответ дан Vincent Fenet, с репутацией 196, 2.02.2017