Perfil de uso de memória de aplicativos Python no Azure Functions
Durante o desenvolvimento ou depois de implantar seu projeto de aplicativo de funções Python local no Azure, é uma boa prática analisar possíveis gargalos de memória em suas funções. Esses afunilamentos podem diminuir o desempenho de suas funções e gerar erros. As instruções a seguir mostram como usar o pacote Python de memory-profiler, que fornece a análise de consumo de memória linha por linha de suas funções à medida que elas são executadas.
Observação
A criação de perfil de memória destina-se apenas à análise de superfície de memória em ambientes de desenvolvimento. Não aplique o criador de perfil de memória em aplicativos de função de produção.
Pré-requisitos
Antes de começar a desenvolver um aplicativo de funções do Python, você deve atender a estes requisitos:
Python 3.7 ou superior. Para verificar a lista completa de versões do Python com suporte no Azure Functions, consulte o Guia do desenvolvedor do Python.
O Azure Functions Core Tools, versão 4.x ou posterior. Verifique sua versão com
func --version
. Para saber mais sobre a atualização, consulte Azure Functions Core Tools no GitHub.Visual Studio Code instalado em uma das plataformas compatíveis.
Uma assinatura ativa do Azure.
Caso você não tenha uma assinatura do Azure, crie uma conta gratuita do Azure antes de começar.
Processo de criação de perfil de memória
Em seu requirements.txt, adicione
memory-profiler
para garantir que o pacote é agrupado com sua implantação. Se você estiver desenvolvendo em seu computador local, talvez queira ativar um ambiente virtual Python e fazer uma resolução de pacotepip install -r requirements.txt
.No script de função (por exemplo, __init__.py para o modelo de programação Python v1 e function_app.py para o modelo v2), adicione as linhas a seguir acima da função
main()
. Essas linhas garantem que o agente raiz relate os nomes dos agentes filho, para que os logs de criação de perfil de memória sejam distinguíveis pelo prefixomemory_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)
Aplique o decorador a seguir acima de qualquer função que precise de criação de perfil de memória. O decorador não funciona diretamente no método
main()
de ponto de entrada de gatilho. Você precisa criar subfunções e decorá-las. Além disso, devido a um problema conhecido do criador de perfil de memória, ao aplicar a uma corrotina assíncrona, o valor retornado da corrotina sempre éNone
.@memory_profiler.profile(stream=profiler_logstream)
Teste o criador de perfil de memória no computador local usando o comando
func host start
do Azure Functions Core Tools. Quando você invoca as funções, elas devem gerar um relatório de uso de memória. O relatório contém o nome do arquivo, a linha de código, o uso de memória, o incremento de memória e o conteúdo da linha.Para verificar os logs de criação de perfil de memória em uma instância de aplicativo de funções existente no Azure, você pode consultar os logs de criação de perfil de memória em invocações recentes com consultas Kusto no 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
Exemplo
Aqui está um exemplo de como executar a criação de perfil de memória em gatilhos HTTP assíncronos e síncronos, chamados "HttpTriggerAsync" e "HttpTriggerSync", respectivamente. Criaremos um aplicativo de funções do Python que simplesmente envia solicitações GET para a página inicial da Microsoft.
Criar um aplicativo de funções do Python
Um aplicativo de funções do Python deve seguir a estrutura de pastas especificada do Azure Functions. Para realizar o scaffold do projeto, é recomendável usar o Azure Functions Core Tools executando os seguintes comandos:
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
Atualizar o conteúdo do arquivo
O requirements.txt define os pacotes que são usados em nosso projeto. Além do Azure Functions SDK e do memory-profiler, introduzimos aiohttp
para solicitações HTTP assíncronas e requests
para chamadas HTTP síncronas.
# requirements.txt
azure-functions
memory-profiler
aiohttp
requests
Crie o gatilho HTTP assíncrono.
Substitua o código no gatilho HTTP assíncrono HttpTriggerAsync/__init__.py pelo código a seguir, que configura o criador de perfil de memória, o formato do agente raiz e a associação de streaming do agente.
# 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
Crie o gatilho HTTP síncrono.
Substitua o código no gatilho HTTP assíncrono HttpTriggerSync/__init__.py pelo código a seguir.
# 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
Aplicativo de funções Python de perfil no ambiente de desenvolvimento local
Depois de fazer todas as alterações acima, há mais algumas etapas para inicializar um ambiente virtual do Python para o runtime do Azure Functions.
Abra um Windows PowerShell ou qualquer shell do Linux como preferir.
Crie um ambiente virtual do Python por
py -m venv .venv
no Windows oupython3 -m venv .venv
no Linux.Ative o ambiente virtual do Python com
.venv\Scripts\Activate.ps1
no Windows PowerShell ousource .venv/bin/activate
no shell do Linux.Restaurar as dependências do Python com
pip install -r requirements.txt
Inicie o runtime do Azure Functions localmente com Azure Functions Core Tools
func host start
Envie uma solicitação GET para
https://localhost:7071/api/HttpTriggerAsync
ouhttps://localhost:7071/api/HttpTriggerSync
.Ela deve mostrar um relatório de criação de perfil de memória semelhante à seção a seguir no Azure Functions 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()
Próximas etapas
Para obter mais informações sobre o desenvolvimento do Python do Azure Functions consulte os seguintes recursos: