Partilhar via


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:

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

  1. 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 por pip install -r requirements.txt.

  2. 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 prefixo 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)
    
  3. 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 é sempre None.

    @memory_profiler.profile(stream=profiler_logstream)
    
  4. Teste o criador de perfil de memória em sua máquina local usando o comando func host startFerramentas 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.

  5. 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.

    Screenshot showing the query memory usage of a Python app in Application Insights.

    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.

  1. Abra um Windows PowerShell ou qualquer shell Linux como preferir.

  2. Crie um ambiente py -m venv .venv virtual Python no Windows ou python3 -m venv .venv no Linux.

  3. Ative o ambiente virtual Python com .venv\Scripts\Activate.ps1 o Windows PowerShell ou source .venv/bin/activate o shell do Linux.

  4. Restaure as dependências do Python com pip install -r requirements.txt

  5. Inicie o tempo de execução do Azure Functions localmente com as Ferramentas Principais do Azure Functions func host start

  6. Envie uma solicitação GET para https://localhost:7071/api/HttpTriggerAsync ou https://localhost:7071/api/HttpTriggerSync.

  7. 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: