Как измерить использование памяти веб-запросом при использовании Werkzeug/Flask?

Есть ли способ измерить объем памяти, выделенный произвольным веб-запросом в приложении Flask/Werkzeug? Под произвольным я подразумеваю, что я бы предпочел метод, который позволяет мне анализировать код на достаточно высоком уровне, чтобы мне не приходилось его изменять для проверки использования памяти различными маршрутами. Если это невозможно, но все же возможно сделать это, обернув отдельные запросы небольшим кодом, пусть будет так.

В PHP-приложении, которое я написал некоторое время назад, я добился этого, вызвав функцию memory_get_peak_usage() как в начале, так и в конце запроса и взяв разницу.

Есть ли аналог в Python/Flask/Werkzeug? Использование Python 2.7.9, если это имеет значение.


person DaveBurns    schedule 06.01.2016    source источник


Ответы (2)


Прежде всего, следует понять основную разницу между обработкой запросов PHP и Python. Грубо говоря, каждый PHP-воркер принимает только один запрос, обрабатывает его и затем умирает (или переинициирует интерпретатор). PHP был разработан непосредственно для него, это язык обработки запросов по своей природе. Таким образом, довольно просто измерить использование памяти для каждого запроса. Пиковое использование памяти запросом равно пиковому использованию рабочей памяти. Это особенность языка.

В то же время Python обычно использует другой подход к обработке запросов. Есть две основные модели — синхронная и асинхронная обработка запросов. Однако оба они имеют одинаковые трудности, когда дело доходит до измерения использования памяти для каждого запроса. Причина в том, что один работник Python за свою жизнь обрабатывает множество запросов (одновременно или последовательно). Таким образом, трудно получить использование памяти именно для запроса.

Однако можно адаптировать базовую структуру и код приложения для выполнения задачи сбора данных об использовании памяти. Одним из возможных решений является использование неких событий. Например, можно вызвать абстрактное событие mem_usage: перед запросом, в начале функции представления, в конце функции представления, в некоторых важных местах бизнес-логики и так далее. Затем должен существовать подписчик на такие события, делающий следующее:

import resource
mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss

Этот подписчик должен накапливать такие данные об использовании и на app_request_teardown/after_request отправлять их в систему сбора метрик с информацией о текущем request.endpoint или маршруте или что-то еще.

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

Дальнейшее чтение о моделях обработки запросов:

person Ivan Velichko    schedule 20.03.2016
comment
Я хорошо знаком с моделью запросов обоих языков. Предположим, что я нахожусь в контролируемой среде, где я выбираю, какой запрос выполняется, и в каждый момент времени будет только один запрос. Существует ли специальный модуль, универсальный или специфичный для Werkzeug, наиболее подходящий для тестирования использования памяти? Спасибо. - person DaveBurns; 21.03.2016
comment
@DaveBurns, как насчет использования sys.settrace? - person Ivan Velichko; 05.05.2016

Другое возможное решение — использовать sys.setrace. С помощью этого инструмента можно измерить использование памяти даже для каждой строки кода. Примеры использования можно найти в проекте memory_profiler. Конечно, это значительно замедлит код.

person Ivan Velichko    schedule 05.05.2016