Uso de memória de aplicativos Python de perfil no Azure Functions
Durante o desenvolvimento ou depois de implantar seu projeto de aplicativo de função Python local no Azure, é uma boa prática analisar possíveis gargalos de memória em suas funções. Tais gargalos podem diminuir o desempenho de suas funções e levar a erros. As instruções a seguir mostram como usar o pacote Python do criador de perfil de memória, que fornece análise de consumo de memória linha por linha de suas funções à medida que são executadas.
Nota
A criação de perfil de memória destina-se apenas à análise do espaço ocupado pela 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ção Python, você deve atender a estes requisitos:
Python 3.7 ou superior. Para verificar a lista completa de versões Python suportadas no Azure Functions, consulte o guia do desenvolvedor do Python.
As Ferramentas Principais do Azure Functions, versão 4.x ou superior. Verifique a sua versão com
func --version
. Para saber mais sobre a atualização, consulte Ferramentas principais do Azure Functions no GitHub.Visual Studio Code instalado em uma das plataformas suportadas.
Uma subscrição ativa do Azure.
Se não tiver uma subscrição do Azure, crie uma conta gratuita do Azure antes de começar.
Processo de criação de perfil de memória
Em seus requisitos.txt, adicione
memory-profiler
para garantir que o pacote seja empacotado com sua implantação. Se você estiver desenvolvendo em sua máquina local, convém ativar um ambiente virtual Python e fazer uma resolução de pacote porpip 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 seguintes linhas acima da
main()
função. Essas linhas garantem que o registrador raiz informe os nomes do registrador 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 seguinte decorador acima de todas as funções que precisam de perfil de memória. O decorador não trabalha diretamente no método do ponto
main()
de entrada do 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 co-rotina assíncrona, o valor de retorno da co-rotina é sempreNone
.@memory_profiler.profile(stream=profiler_logstream)
Teste o criador de perfil de memória em sua máquina local usando o comando
func host start
Ferramentas Principais do Azure Functions. Quando você invoca as funções, elas devem gerar um relatório de uso de memória. O relatório contém nome de arquivo, linha de código, uso de memória, incremento de memória e o conteúdo da linha nele.Para verificar os logs de criação de perfil de memória em uma instância de aplicativo de função existente no Azure, você pode consultar os logs de criação de perfil de memória para invocações recentes com consultas Kusto em 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 execução de criação de perfil de memória em um gatilho HTTP assíncrono e síncrono, chamados "HttpTriggerAsync" e "HttpTriggerSync", respectivamente. Vamos criar um aplicativo de função Python que simplesmente envia solicitações GET para a página inicial da Microsoft.
Criar um aplicativo de função Python
Um aplicativo de função Python deve seguir a estrutura de pastas especificada do Azure Functions. Para organizar o projeto, recomendamos usar as Ferramentas Principais do Azure Functions 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
Os requisitos.txt define os pacotes que são usados em nosso projeto. Além do SDK do Azure Functions e do criador de perfil de memória, apresentamos 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 registrador raiz e a ligação de streaming do registrador.
# 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ção Python de perfil em ambiente de desenvolvimento local
Depois de fazer as alterações acima, há mais algumas etapas para inicializar um ambiente virtual Python para o tempo de execução do Azure Functions.
Abra um Windows PowerShell ou qualquer shell Linux como preferir.
Crie um ambiente
py -m venv .venv
virtual Python no Windows oupython3 -m venv .venv
no Linux.Ative o ambiente virtual Python com
.venv\Scripts\Activate.ps1
o Windows PowerShell ousource .venv/bin/activate
o shell do Linux.Restaure as dependências do Python com
pip install -r requirements.txt
Inicie o tempo de execução do Azure Functions localmente com as Ferramentas Principais do Azure Functions
func host start
Envie uma solicitação GET para
https://localhost:7071/api/HttpTriggerAsync
ouhttps://localhost:7071/api/HttpTriggerSync
.Ele deve mostrar um relatório de criação de perfil de memória semelhante à seção a seguir nas Ferramentas Principais do Azure Functions.
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óximos passos
Para obter mais informações sobre o desenvolvimento Python do Azure Functions, consulte os seguintes recursos: