Partager via


Profiler l’utilisation de la mémoire des applications Python dans Azure Functions

Pendant le développement ou après le déploiement de votre projet d’application de fonction Python local dans Azure, il est recommandé d’analyser les goulots d’étranglement de mémoire potentiels dans vos fonctions. De tels goulots d’étranglement peuvent réduire les performances de vos fonctions et entraîner des erreurs. Les instructions suivantes vous montrent comment utiliser le package Python du profileur de mémoire, qui permet d’analyser ligne par ligne la consommation de mémoire de vos fonctions au fur et à mesure de leur exécution.

Notes

Le profilage de la mémoire est destiné uniquement à l’analyse de l’empreinte mémoire dans les environnements de développement. N’appliquez pas le profileur de mémoire sur les applications de fonction de production.

Prérequis

Avant de commencer à développer une application de fonction Python, vous devez respecter les conditions suivantes :

Si vous n’avez pas d’abonnement Azure, créez un compte gratuit Azure avant de commencer.

Processus de profilage de la mémoire

  1. Dans votre requirements.txt, ajoutez memory-profiler pour vous assurer que le package est groupé à votre déploiement. Si vous développez sur votre ordinateur local, vous souhaiterez peut-être activer un environnement virtuel Python et effectuer une résolution de package par pip install -r requirements.txt.

  2. Dans votre script de fonction (par exemple, __init__.py pour le modèle de programmation Python v1 et function_app.py pour le modèle v2), ajoutez les lignes suivantes au-dessus de la fonction main(). Ces lignes permettent de s’assurer que l’enregistreur d'événements racine signale les noms d’enregistreur d’événements enfants, afin que les journaux de profilage de la mémoire se distinguent par le préfixe 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. Appliquez l’élément décoratif suivant au-dessus des fonctions nécessitant un profilage de la mémoire. Cet décorateur ne fonctionne pas directement sur la méthode de point d’entrée du déclencheur main(). Vous devez créer des sous-fonctions et les décorer. En outre, en raison d’un problème connu du profileur de mémoire, lors de l’application à une coroutine asynchrone, la valeur de retour de la coroutine est toujours de None.

    @memory_profiler.profile(stream=profiler_logstream)
    
  4. Testez le profileur de mémoire sur votre ordinateur local à l’aide de la commande func host start d’Azure Functions Core Tools. Lorsque vous appelez les fonctions, elles doivent générer un rapport d’utilisation de la mémoire. Celui-ci contient le nom de fichier, la ligne de code, l’utilisation de la mémoire, l’incrément de mémoire et le contenu de ligne qui s’y trouve.

  5. Pour vérifier les journaux de profilage de la mémoire sur une instance d’application de fonction existante dans Azure, vous pouvez interroger les journaux de profilage de la mémoire des appels récents avec les requêtes Kusto suivantes dans Journaux d’activité d’Application Insights.

    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
    

Exemple

Voici un exemple d’exécution du profilage de la mémoire sur des déclencheurs HTTP asynchrone et synchrone, nommés respectivement « HttpTriggerAsync » et « HttpTriggerSync ». Nous allons créer une application de fonction Python qui envoie simplement des requêtes GET à la page d’accueil de Microsoft.

Créer une application de fonction Python

Une application de fonction Python doit suivre la structure de dossiers Azure Functions spécifiée. Pour générer un modèle de structure pour le projet, nous vous recommandons d’utiliser Azure Functions Core Tools en exécutant les commandes suivantes :

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

Mettre à jour les contenus de fichiers

Le requirements.txt définit les packages utilisés dans notre projet. En plus du kit SDK Azure Functions et profileur de mémoire, nous avons introduit aiohttp pour les requêtes HTTP asynchrones et requests pour les appels HTTP synchrones.

# requirements.txt

azure-functions
memory-profiler
aiohttp
requests

Créez le déclencheur HTTP asynchrone.

Remplacez le code dans le déclencheur HTTP asynchrone HttpTriggerAsync/__init__.py par le code suivant, qui configure le profileur de mémoire, le format d’enregistreur d’événements racine et la liaison de streaming d’enregistreur d’événements.

# 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

Créez le déclencheur HTTP synchrone.

Remplacez le code dans le déclencheur HTTP asynchrone HttpTriggerSync/__init__.py par le code suivant.

# 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

Profiler une application de fonction Python dans un environnement de développement local

Après avoir apporté toutes les modifications ci-dessus, quelques étapes supplémentaires permettent d’initialiser un environnement virtuel Python pour le runtime Azure Functions.

  1. Ouvrez Windows PowerShell ou n’importe quel interpréteur de commandes Linux comme vous le souhaitez.

  2. Créez un environnement virtuel Python en py -m venv .venv dans Windows ou python3 -m venv .venv dans Linux.

  3. Activez l’environnement virtuel Python avec .venv\Scripts\Activate.ps1 dans Windows PowerShell ou source .venv/bin/activate dans l’interpréteur de commandes Linux.

  4. Restaurer les dépendances Python avec pip install -r requirements.txt

  5. Démarrez le runtime Azure Functions localement avec Azure Functions Core Tools func host start

  6. Envoyez une requête GET à https://localhost:7071/api/HttpTriggerAsync ou https://localhost:7071/api/HttpTriggerSync.

  7. Un rapport de profilage de la mémoire similaire à la section suivante devrait s’afficher dans 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()
    

Étapes suivantes

Pour plus d’informations sur le développement Python Azure Functions, consultez les ressources suivantes :