Недавно я заинтересовался алгоритмами и начал изучать их, написав наивную реализацию, а затем оптимизировав ее различными способами.
Я уже знаком со стандартным модулем Python для профилирования среды выполнения (для большинства вещей я считаю, что магической функции timeit в IPython достаточно), но я также заинтересован в использовании памяти, чтобы также изучить эти компромиссы ( например, стоимость кэширования таблицы ранее вычисленных значений или пересчет их при необходимости). Есть ли модуль, который будет профилировать использование памяти данной функции для меня?
Ответы:
На этот вопрос уже ответили: Профилировщик памяти Python
В основном вы делаете что-то подобное (цитируется из Guppy-PE ):
источник
Python 3.4 включает в себя новый модуль:
tracemalloc
. Он предоставляет подробную статистику о том, какой код выделяет больше всего памяти. Вот пример, который отображает три верхние строки, выделяющие память.И вот результаты:
Когда утечка памяти не утечка?
Этот пример хорош, когда память все еще удерживается в конце вычислений, но иногда у вас есть код, который выделяет много памяти, а затем освобождает все это. Технически это не утечка памяти, но она использует больше памяти, чем вы думаете. Как вы можете отслеживать использование памяти, когда все это освобождается? Если это ваш код, вы, вероятно, можете добавить отладочный код, чтобы делать снимки во время его работы. Если нет, вы можете запустить фоновый поток для мониторинга использования памяти во время работы основного потока.
Вот предыдущий пример, где весь код был перемещен в
count_prefixes()
функцию. Когда эта функция возвращается, вся память освобождается. Я также добавил несколькоsleep()
вызовов для имитации длительного расчета.Когда я запускаю эту версию, использование памяти уменьшилось с 6 МБ до 4 КБ, потому что функция освободила всю свою память после завершения.
Теперь вот версия, вдохновленная другим ответом, который запускает второй поток для мониторинга использования памяти.
resource
Модуль позволяет проверить текущее использование памяти, и сохранить снимок с использованием пика памяти. Очередь позволяет основному потоку сообщать потоку монитора памяти, когда печатать свой отчет и завершать работу. Когда он работает, он показывает память, используемуюlist()
вызовом:Если вы работаете в Linux, вы можете найти
/proc/self/statm
более полезный, чемresource
модуль.источник
long_running()
внутриcount_prefixes()
функции, максимальные значения RSS не будут печататься до тех пор, пока не будутlong_running()
возвращены. Или я ошибаюсь?memory_monitor()
выполняется в отдельном потокеcount_prefixes()
, поэтому единственный способ повлиять на другой - это GIL и очередь сообщений, которые я передаюmemory_monitor()
. Я подозреваю, что приcount_prefixes()
вызовахsleep()
это поощряет переключение контекста потока. Если вы наlong_running()
самом деле не занимает много времени, контекст потока может не переключаться, пока вы не нажмете наsleep()
обратный вызовcount_prefixes()
. Если это не имеет смысла, напишите новый вопрос и ссылку на него отсюда.Если вы хотите посмотреть только на использование памяти объектом ( ответ на другой вопрос )
источник
asizeof
asizeof
может способствовать RSS, да. Я не уверен, что еще ты имеешь в виду под "родственником".tracemalloc
решение на величину меньшеРаскрытие информации:
Но приятно из-за своей простоты:
Просто введите,
using("Label")
где вы хотите увидеть, что происходит. Напримеристочник
usage[2]
вас, вы посмотритеru_maxrss
, что является лишь частью процесса, который является резидентным . Это не сильно поможет, если процесс был перенесен на диск, даже частично.resource
модуль для Unix, который не работает под Windowsru_maxrss
(то естьusage[2]
) являются килобайты, а не страницы, поэтому нет необходимости умножать это число наresource.getpagesize()
.Поскольку принятый ответ, а также следующий по количеству голосов ответ, на мой взгляд, имеют некоторые проблемы, я хотел бы предложить еще один ответ, который основывается на ответе Игоря Б. с некоторыми небольшими, но важными изменениями.
Это решение позволяет запускать профилирование на любом обертывание вызова функции с
profile
функцией и называть его, или украшая вашу функцию / метод с@profile
декоратором.Первый метод полезен, когда вы хотите профилировать какой-либо сторонний код, не связываясь с его источником, тогда как второй метод немного «чище» и работает лучше, когда вы не против изменить источник функции / метода, который вы хочу в профиль.
Я также изменил вывод, чтобы вы получили RSS, VMS и общую память. Меня не волнуют значения «до» и «после», а только дельта, поэтому я удалил их (если вы сравниваете с ответом Игоря Б.).
Код профилирования
Пример использования, при условии, что приведенный выше код сохранен как
profile.py
:Это должно привести к выводу, подобному следующему:
Пара важных заключительных замечаний:
profile(my_function, arg)
для профилированияmy_function(arg)
источник
Ниже приведен простой декоратор функций, который позволяет отследить, сколько памяти потребляет процесс до вызова функции, после вызова функции и в чем разница:
Вот мой блог, который описывает все детали. ( архивная ссылка )
источник
process.memory_info().rss
неprocess.get_memory_info().rss
, по крайней мере , в убунту и Python 3.6. Связанный stackoverflow.com/questions/41012058/psutil-error-on-macosможет быть, это поможет:
< посмотреть дополнительно >
источник
источник