Профилирование использования памяти приложениями Python в службе "Функции Azure"
Во время разработки или после развертывания локального проекта приложения-функции Python в Azure рекомендуется анализировать потенциальные ограничения со стороны памяти в функциях. Такие ограничения могут снизить производительность функций и привести к ошибкам. В следующих инструкциях показано, как использовать пакет Python для профилировщика памяти, который предоставляет анализ потребления памяти по строкам функций при выполнении.
Примечание.
Профилирование памяти предназначено только для анализа объема памяти в средах разработки. Не применяйте профилировщик памяти в рабочих приложениях-функциях.
Необходимые компоненты
Прежде чем приступить к разработке приложения-функции Python, необходимо выполнить следующие требования:
Python 3.7 или более поздней версии. Полный список поддерживаемых версий Python в службе "Функции Azure" см. в руководстве разработчика Python.
Функции Azure Core Tools версии 4.x или более поздней. Проверьте версию с
func --version
помощью . Дополнительные сведения об обновлении см. в статье Функции Azure Core Tools на сайте GitHub.Приложение Visual Studio Code, установленное на одной из поддерживаемых платформ.
Активная подписка Azure.
Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начинать работу.
Процесс профилирования памяти
В requirements.txt добавьте
memory-profiler
пакет, чтобы убедиться, что пакет упаковается в развертывание. Если вы разрабатываете на локальном компьютере, вы можете активировать виртуальную среду Python и выполнить разрешение пакета.pip install -r requirements.txt
В скрипте функции (например, __init__.py для модели программирования Python версии 1 и function_app.py для модели версии 2) добавьте следующие строки над
main()
функцией. Эти строки гарантируют, что корневой средство ведения журнала сообщает имена дочерних средств ведения журнала, чтобы журналы профилирования памяти отличались префиксомmemory_profiler_logs
.import logging import memory_profiler root_logger = logging.getLogger() root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s")) profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
Примените следующий декоратор над любыми функциями, которым требуется профилирование памяти. Декоратор не работает непосредственно с методом точки
main()
входа триггера. Необходимо создать подфункции и дополнить их. Кроме того, из-за известной проблемы с профилировщиком памяти при применении к асинхронной корутине возвращаемое значение всегдаNone
.@memory_profiler.profile(stream=profiler_logstream)
Проверьте профилировщик памяти на локальном компьютере с помощью команды
func host start
Функции Azure Core Tools. При вызове функций они должны создать отчет об использовании памяти. Отчет содержит имя файла, строку кода, использование памяти, увеличение памяти и содержимое строки.Чтобы проверить журналы профилирования памяти в существующем экземпляре приложения-функции в Azure, можно запросить журналы профилирования памяти для последних вызовов с помощью запросов Kusto в Application Insights, logs.
traces | where timestamp > ago(1d) | where message startswith_cs "memory_profiler_logs:" | parse message with "memory_profiler_logs: " LineNumber " " TotalMem_MiB " " IncreMem_MiB " " Occurrences " " Contents | union ( traces | where timestamp > ago(1d) | where message startswith_cs "memory_profiler_logs: Filename: " | parse message with "memory_profiler_logs: Filename: " FileName | project timestamp, FileName, itemId ) | project timestamp, LineNumber=iff(FileName != "", FileName, LineNumber), TotalMem_MiB, IncreMem_MiB, Occurrences, Contents, RequestId=itemId | order by timestamp asc
Пример
Ниже приведен пример выполнения профилирования памяти на асинхронном и синхронном триггере HTTP с именем HttpTriggerAsync и HttpTriggerSync соответственно. Мы создадим приложение-функцию Python, которое просто отправляет запросы GET на домашнюю страницу Майкрософт.
Создание приложения-функции Python
Приложение-функция Python должно соответствовать заданной в службе "Функции Azure" структуре папок. Чтобы сформировать шаблон проекта, рекомендуется использовать Azure Functions Core Tools, выполнив следующие команды:
func init PythonMemoryProfilingDemo --python
cd PythonMemoryProfilingDemo
func new -l python -t HttpTrigger -n HttpTriggerAsync -a anonymous
func new -l python -t HttpTrigger -n HttpTriggerSync -a anonymous
Обновление содержимого файла
Requirements.txt определяет пакеты, используемые в нашем проекте. Помимо пакета SDK для службы "Функции Azure" и профилировщика памяти, мы представляем aiohttp
для асинхронных HTTP-запросов и requests
для синхронных HTTP-вызовов.
# requirements.txt
azure-functions
memory-profiler
aiohttp
requests
Создайте асинхронный триггер HTTP.
Замените код в асинхронном триггере HTTPTriggerAsync/__init__.py следующим кодом, который настраивает профилировщик памяти, формат корневого средства ведения журнала и привязку потоковой передачи средства ведения журнала.
# HttpTriggerAsync/__init__.py
import azure.functions as func
import aiohttp
import logging
import memory_profiler
# Update root logger's format to include the logger name. Ensure logs generated
# from memory profiler can be filtered by "memory_profiler_logs" prefix.
root_logger = logging.getLogger()
root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
async def main(req: func.HttpRequest) -> func.HttpResponse:
await get_microsoft_page_async('https://microsoft.com')
return func.HttpResponse(
f"Microsoft page loaded.",
status_code=200
)
@memory_profiler.profile(stream=profiler_logstream)
async def get_microsoft_page_async(url: str):
async with aiohttp.ClientSession() as client:
async with client.get(url) as response:
await response.text()
# @memory_profiler.profile does not support return for coroutines.
# All returns become None in the parent functions.
# GitHub Issue: https://github.com/pythonprofilers/memory_profiler/issues/289
Создайте синхронный триггер HTTP.
Замените код в асинхронном триггере HTTPTriggerSync/__init__.py следующим кодом.
# HttpTriggerSync/__init__.py
import azure.functions as func
import requests
import logging
import memory_profiler
# Update root logger's format to include the logger name. Ensure logs generated
# from memory profiler can be filtered by "memory_profiler_logs" prefix.
root_logger = logging.getLogger()
root_logger.handlers[0].setFormatter(logging.Formatter("%(name)s: %(message)s"))
profiler_logstream = memory_profiler.LogFile('memory_profiler_logs', True)
def main(req: func.HttpRequest) -> func.HttpResponse:
content = profile_get_request('https://microsoft.com')
return func.HttpResponse(
f"Microsoft page response size: {len(content)}",
status_code=200
)
@memory_profiler.profile(stream=profiler_logstream)
def profile_get_request(url: str):
response = requests.get(url)
return response.content
Профилирование приложения-функции Python в локальной среде разработки
После внесения указанных выше изменений можно выполнить несколько дополнительных действий, чтобы инициализировать виртуальную среду Python для среды выполнения Функции Azure.
Откройте Windows PowerShell или любую оболочку Linux по своему выбору.
Создайте виртуальную среду Python с помощью
py -m venv .venv
в ОС Windows илиpython3 -m venv .venv
в Linux.Активируйте виртуальную среду Python с
.venv\Scripts\Activate.ps1
помощью Windows PowerShell илиsource .venv/bin/activate
оболочки Linux.Восстановите зависимости Python с помощью
pip install -r requirements.txt
Запустите среду выполнения службы "Функции Azure" на локальном компьютере с помощью
func host start
Azure Functions Core Tools.Отправьте запрос GET в
https://localhost:7071/api/HttpTriggerAsync
илиhttps://localhost:7071/api/HttpTriggerSync
.Он должен отображать отчет профилирования памяти, аналогичный следующему разделу в Функции Azure Core Tools.
Filename: <ProjectRoot>\HttpTriggerAsync\__init__.py Line # Mem usage Increment Occurrences Line Contents ============================================================ 19 45.1 MiB 45.1 MiB 1 @memory_profiler.profile 20 async def get_microsoft_page_async(url: str): 21 45.1 MiB 0.0 MiB 1 async with aiohttp.ClientSession() as client: 22 46.6 MiB 1.5 MiB 10 async with client.get(url) as response: 23 47.6 MiB 1.0 MiB 4 await response.text()
Следующие шаги
Дополнительные сведения о разработках под Python в рамках службы "Функции Azure" см. в статьях ниже.
- Azure Functions Python Developer Guide (Справочник по Функциям Azure для разработчика Python)
- Рекомендации по функциям Azure
- Справочник разработчика по функциям Azure