Generar perfiles de uso de memoria de aplicaciones de Python en Azure Functions
Durante el desarrollo o después de implementar el proyecto de aplicación de función de Python local en Azure, es recomendable analizar los posibles cuellos de botella de memoria en las funciones. Estos cuellos de botella pueden reducir el rendimiento de las funciones y provocar errores. Las siguientes instrucciones muestran cómo usar el paquete de Python del generador de perfiles de memoria, que proporciona análisis de consumo de memoria de línea por línea de las funciones a medida que se ejecutan.
Nota
La generación de perfiles de memoria solo está diseñada para el análisis de la superficie de memoria en entornos de desarrollo. No aplique el generador de perfiles de memoria en las aplicaciones de función de producción.
Prerrequisitos
Antes de empezar a desarrollar una aplicación de función de Python, debe cumplir estos requisitos:
Python 3.7 o versiones posteriores. Para consultar la lista completa de las versiones compatibles de Python en Azure Functions, consulte la Guía para desarrolladores de Python.
La versión 4.x de Azure Functions Core Tools, o cualquier versión posterior. Compruebe su versión con
func --version
. Para más información sobre la actualización, consulte Azure Functions Core Tools en GitHub.Tener instalado Visual Studio Code en una de las plataformas compatibles.
Una suscripción de Azure activa.
Si no tiene una suscripción a Azure, cree una cuenta gratuita de Azure antes de empezar.
Proceso de generación de perfiles de memoria
En el requirements.txt, agregue
memory-profiler
para asegurarse de que el paquete se agrupa con la implementación. Si está desarrollando en el equipo local, puede que desee activar un entorno virtual de Python y realizar una resolución de paquetes mediantepip install -r requirements.txt
.En el script de función (por ejemplo, __init__.py para el modelo de programación de Python v1 y function_app.py para el modelo v2), agregue las líneas siguientes encima de la función
main()
. Estas líneas garantizan que el registrador raíz informe de los nombres del registrador secundario, de modo que el prefijo pueda distinguir los registros de generación de perfiles de memoriamemory_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 el siguiente decorador sobre cualquier función que necesite la generación de perfiles de memoria. El decorador no funciona directamente en el método
main()
del punto de entrada del desencadenador. Debe crear subfunciones y decorarlas. Asimismo, debido a un problema conocido de memory-profiler, al aplicar a una corrutina asincrónica, el valor devuelto de la corrutina siempre esNone
.@memory_profiler.profile(stream=profiler_logstream)
Pruebe el generador de perfiles de memoria en el equipo local mediante el comando de Azure Functions Core Tools
func host start
. Al invocar las funciones, deben generar un informe de uso de memoria. El informe contiene el nombre de archivo, la línea de código, el uso de memoria, el incremento de memoria y el contenido de línea que contiene.Para comprobar los registros de perfil de memoria en una instancia de aplicación de función existente en Azure, puede consultar los registros de generación de perfiles de la memoria para las invocaciones recientes con las consultas de Kusto en Application Insights y en los registros.
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
Ejemplo
Este es un ejemplo de cómo realizar la generación de perfiles de memoria en un desencadenador HTTP asincrónicos y sincrónicos, denominados "HttpTriggerAsync" y "HttpTriggerSync", respectivamente. Crearemos una aplicación de función de Python que simplemente envíe solicitudes GET a la Página principal de Microsoft.
Creación de la aplicación de funciones de Python
Una aplicación de funciones de Python debe seguir la estructura de carpetasde Azure Functions especificada. Para aplicar la técnica scaffolding al proyecto, se recomienda usar el Azure Functions Core Tools mediante la ejecución de los siguientes 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
Actualizar contenidos del archivo
El requirements.txt define los paquetes que se usan en nuestro proyecto. Además del SDK de Azure Functions y el generador de perfiles de memoria, se introduce aiohttp
para las solicitudes HTTP asincrónicas y requests
para las llamadas HTTP sincrónicas.
# requirements.txt
azure-functions
memory-profiler
aiohttp
requests
Cree el desencadenador HTTP asincrónico.
Reemplace el código del desencadenador HTTP asincrónico HttpTriggerAsync/__init__.py por el código siguiente, que configura el generador de perfiles de memoria, el formato del registrador raíz y el enlace de streaming del 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
Cree el desencadenador HTTP sincrónico.
Reemplace el código del desencadenador HTTP asincrónico HttpTriggerSync/__init__.py por el código siguiente.
# 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
Generar perfiles de la aplicación de funciones de Python en el entorno de desarrollo local
Después de realizar todos los cambios anteriores, hay algunos pasos más para inicializar un entorno virtual de Python para el tiempo de ejecución de Azure Functions.
Abra Windows PowerShell o cualquier Shell de Linux de su preferencia.
Cree un entorno virtual de Python
py -m venv .venv
en Windows opython3 -m venv .venv
en Linux.Active el entorno virtual de Python con
.venv\Scripts\Activate.ps1
en Windows PowerShell osource .venv/bin/activate
en el shell de Linux.Restaure las dependencias de Python con
pip install -r requirements.txt
Inicie el tiempo de ejecución de Azure Functions de forma local con Azure Functions Core Tools
func host start
Envíe una solicitud GET a la aplicación
https://localhost:7071/api/HttpTriggerAsync
ohttps://localhost:7071/api/HttpTriggerSync
.Debería mostrar un informe de generación de perfiles de memoria similar a la sección siguiente en 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()
Pasos siguientes
Para obtener más información sobre el desarrollo de Python de Azure Functions, consulte los siguientes recursos: