Condividi tramite


Profila l'utilizzo della memoria delle app Python in Funzioni di Azure

Durante lo sviluppo o dopo la distribuzione del progetto di app per le funzioni Python locale in Azure, è consigliabile analizzare i potenziali colli di bottiglia della memoria nelle funzioni. Tali colli di bottiglia possono ridurre le prestazioni delle funzioni e causare errori. Le istruzioni seguenti illustrano come usare il pacchetto Python memory-profiler , che fornisce l'analisi del consumo di memoria line-by-line delle funzioni durante l'esecuzione.

Nota

La profilatura della memoria è destinata solo all'analisi del footprint di memoria negli ambienti di sviluppo. Non applicare il profiler di memoria alle app per le funzioni di produzione.

Prerequisiti

Prima di iniziare a sviluppare un'app per le funzioni Python, è necessario soddisfare questi requisiti:

Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.

Processo di profilatura della memoria

  1. Nel file requirements.txt aggiungere memory-profiler per assicurarsi che il pacchetto sia incluso nella distribuzione. Se si sviluppa nel computer locale, è possibile attivare un ambiente virtuale Python ed eseguire una risoluzione del pacchetto tramite pip install -r requirements.txt.

  2. Nello script della funzione (ad esempio, __init__.py per il modello di programmazione Python v1 e function_app.py per il modello v2), aggiungere le righe seguenti sopra la main() funzione. Queste righe assicurano che il logger radice restituisca i nomi dei logger figlio, in modo che i log di profilatura della memoria siano distinguibili dal prefisso 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. Applicare l'elemento Decorator seguente sopra tutte le funzioni che richiedono la profilatura della memoria. L'elemento Decorator non funziona direttamente sul metodo del punto main() di ingresso del trigger. È necessario creare sottofunzioni e decorarle. Inoltre, a causa di un problema noto di memory-profiler, quando si applica a una coroutine asincrona, il valore restituito della coroutine è sempre None.

    @memory_profiler.profile(stream=profiler_logstream)
    
  4. Testare il profiler di memoria nel computer locale usando Funzioni di Azure comando func host startCore Tools . Quando si richiamano le funzioni, devono generare un report sull'utilizzo della memoria. Il report contiene il nome file, la riga di codice, l'utilizzo della memoria, l'incremento della memoria e il contenuto della riga.

  5. Per controllare i log di profilatura della memoria in un'istanza esistente dell'app per le funzioni in Azure, è possibile eseguire query sui log di profilatura della memoria per le chiamate recenti con query Kusto in Application Insights, Log.

    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
    

Esempio

Ecco un esempio di esecuzione della profilatura della memoria in un trigger HTTP asincrono e sincrono, denominato rispettivamente "HttpTriggerAsync" e "HttpTriggerSync". Verrà compilata un'app per le funzioni Python che invia semplicemente richieste GET alla home page di Microsoft.

Creare un'app per le funzioni Python

Un'app per le funzioni Python deve seguire Funzioni di Azure struttura di cartelle specificata. Per eseguire lo scaffolding del progetto, è consigliabile usare Funzioni di Azure Core Tools eseguendo i comandi seguenti:

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

Aggiornare il contenuto del file

Requirements.txt definisce i pacchetti usati nel progetto. Oltre a Funzioni di Azure SDK e memory-profiler, vengono introdotti aiohttp per le richieste HTTP asincrone e requests per le chiamate HTTP sincrone.

# requirements.txt

azure-functions
memory-profiler
aiohttp
requests

Creare il trigger HTTP asincrono.

Sostituire il codice nel trigger HTTP asincrono HttpTriggerAsync/__init__.py con il codice seguente, che configura il profiler di memoria, il formato del logger radice e l'associazione di streaming del logger.

# 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

Creare il trigger HTTP sincrono.

Sostituire il codice nel trigger HTTP asincrono HttpTriggerSync/__init__.py con il codice seguente.

# 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

Profilatura dell'app per le funzioni Python nell'ambiente di sviluppo locale

Dopo aver apportato le modifiche precedenti, è necessario eseguire altri passaggi per inizializzare un ambiente virtuale Python per Funzioni di Azure runtime.

  1. Aprire una shell di Windows PowerShell o Linux come si preferisce.

  2. Creare un ambiente virtuale Python in py -m venv .venv Windows o python3 -m venv .venv in Linux.

  3. Attivare l'ambiente virtuale Python con .venv\Scripts\Activate.ps1 in Windows PowerShell o source .venv/bin/activate nella shell Linux.

  4. Ripristinare le dipendenze python con pip install -r requirements.txt

  5. Avviare il runtime di Funzioni di Azure in locale con Funzioni di Azure Core Toolsfunc host start

  6. Inviare una richiesta GET a https://localhost:7071/api/HttpTriggerAsync o https://localhost:7071/api/HttpTriggerSync.

  7. Dovrebbe essere visualizzato un report di profilatura della memoria simile alla sezione seguente in Funzioni di 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()
    

Passaggi successivi

Per altre informazioni sullo sviluppo di Funzioni di Azure Python, vedere le risorse seguenti: