Profilera minnesanvändning för Python-appar i Azure Functions
Under utvecklingen eller efter distributionen av ditt lokala Python-funktionsappsprojekt till Azure är det en bra idé att analysera potentiella minnesflaskhalsar i dina funktioner. Sådana flaskhalsar kan minska prestandan för dina funktioner och leda till fel. Följande instruktioner visar hur du använder Python-paketet memory-profiler , som tillhandahåller analys av minnesförbrukning rad för rad av dina funktioner när de körs.
Kommentar
Minnesprofilering är endast avsedd för analys av minnesfotavtryck i utvecklingsmiljöer. Använd inte minnesprofilering på produktionsfunktionsappar.
Förutsättningar
Innan du börjar utveckla en Python-funktionsapp måste du uppfylla följande krav:
Python 3.7 eller senare. Om du vill kontrollera den fullständiga listan över Python-versioner som stöds i Azure Functions kan du läsa utvecklarguiden för Python.
Azure Functions Core Tools, version 4.x eller senare. Kontrollera din version med
func --version
. Mer information om uppdatering finns i Azure Functions Core Tools på GitHub.Visual Studio Code installerat på en av de plattformar som stöds.
En aktiv Azure-prenumeration.
Om du inte har en Azure-prenumeration skapar du ett kostnadsfritt Azure-konto innan du börjar.
Minnesprofileringsprocess
I din requirements.txt lägger du till
memory-profiler
för att säkerställa att paketet paketeras med din distribution. Om du utvecklar på den lokala datorn kanske du vill aktivera en virtuell Python-miljö och utföra en paketmatchning medpip install -r requirements.txt
.Lägg till följande rader ovanför
main()
funktionen i funktionsskriptet (till exempel __init__.py för python v1-programmeringsmodellen och function_app.py för v2-modellen). Dessa rader ser till att rotloggaren rapporterar de underordnade loggningsnamnen, så att minnesprofileringsloggarna kan särskiljas med prefixetmemory_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)
Använd följande dekoratör ovanför alla funktioner som behöver minnesprofilering. Dekoratören fungerar inte direkt på utlösarens startpunktsmetod
main()
. Du måste skapa underfunktioner och dekorera dem. På grund av ett känt problem med minnesprofilering är coroutine-returvärdet alltid närNone
det gäller en asynkron koroutin.@memory_profiler.profile(stream=profiler_logstream)
Testa minnesprofileraren på den lokala datorn med hjälp av kommandot
func host start
Azure Functions Core Tools . När du anropar funktionerna bör de generera en minnesanvändningsrapport. Rapporten innehåller filnamn, kodrad, minnesanvändning, minnesökning och radinnehåll i den.Om du vill kontrollera minnesprofileringsloggarna på en befintlig funktionsappinstans i Azure kan du fråga minnesprofileringsloggarna efter de senaste anropen med Kusto-frågor i Application Insights, Loggar.
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
Exempel
Här är ett exempel på hur du utför minnesprofilering på en asynkron och en synkron HTTP-utlösare med namnet "HttpTriggerAsync" respektive "HttpTriggerSync". Vi skapar en Python-funktionsapp som helt enkelt skickar ut GET-begäranden till Microsofts startsida.
Skapa en Python-funktionsapp
En Python-funktionsapp bör följa den angivna mappstrukturen i Azure Functions. För att skapa en autogenerering av projektet rekommenderar vi att du använder Azure Functions Core Tools genom att köra följande kommandon:
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
Uppdatera filinnehåll
Requirements.txt definierar de paket som används i vårt projekt. Förutom Azure Functions SDK och memory-profiler introducerar aiohttp
vi för asynkrona HTTP-begäranden och requests
synkrona HTTP-anrop.
# requirements.txt
azure-functions
memory-profiler
aiohttp
requests
Skapa den asynkrona HTTP-utlösaren.
Ersätt koden i den asynkrona HTTP-utlösaren HttpTriggerAsync/__init__.py med följande kod, som konfigurerar minnesprofilering, rotloggningsformat och loggningsströmningsbindning.
# 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
Skapa den synkrona HTTP-utlösaren.
Ersätt koden i den asynkrona HTTP-utlösaren HttpTriggerSync/__init__.py med följande kod.
# 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
Profilera Python-funktionsapp i lokal utvecklingsmiljö
När du har gjort ändringarna ovan finns det några steg till för att initiera en virtuell Python-miljö för Azure Functions-körning.
Öppna en Windows PowerShell eller ett Linux-gränssnitt som du föredrar.
Skapa en virtuell Python-miljö
py -m venv .venv
i Windows ellerpython3 -m venv .venv
i Linux.Aktivera den virtuella Python-miljön med
.venv\Scripts\Activate.ps1
i Windows PowerShell ellersource .venv/bin/activate
i Linux-gränssnittet.Återställa Python-beroenden med
pip install -r requirements.txt
Starta Azure Functions-körningen lokalt med Azure Functions Core Tools
func host start
Skicka en GET-begäran till
https://localhost:7071/api/HttpTriggerAsync
ellerhttps://localhost:7071/api/HttpTriggerSync
.Den bör visa en minnesprofileringsrapport som liknar följande avsnitt i 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()
Nästa steg
Mer information om Azure Functions Python-utveckling finns i följande resurser: