Profilazione delle applicazioni Python

Questa pagina descrive come modificare l'applicazione Python per acquisire i dati di profilazione e inviarli al tuo progetto Google Cloud. Per informazioni generali sulla profilazione, vedi Concetti di profilazione.

Tipi di profilo per Python:

  • Tempo CPU
  • Tempo totale di esecuzione (thread principale)

Versioni del linguaggio Python supportate:

  • Python 3.6-3.11.0.

Versioni dell'agente di profilazione supportate:

  • È supportata la versione più recente dell'agente. In generale, le release più vecchie di un anno non sono supportate. Ti consigliamo di utilizzare la versione dell'agente rilasciata più di recente.

Sistemi operativi supportati:

  • Linux. La profilazione delle applicazioni Python è supportata per i kernel Linux la cui libreria C standard è implementata con glibc o con musl. Per informazioni di configurazione specifiche per i kernel Linux Alpine, vedi Esecuzione su Linux Alpine.

Ambienti supportati:

Attivazione dell'API Profiler

Prima di utilizzare l'agente di profilazione, assicurati che l'API Profiler sottostante sia abilitata. Puoi controllare lo stato dell'API e abilitarla, se necessario, utilizzando Google Cloud CLI o la console Google Cloud :

Interfaccia a riga di comando gcloud

  1. Se non hai ancora installato Google Cloud CLI sulla tua workstation, consulta la documentazione di Google Cloud CLI.

  2. Esegui questo comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Per ulteriori informazioni, vedi gcloud services.

Console Google Cloud

  1. Enable the required API.

    Enable the API

  2. Se viene visualizzato il messaggio API abilitata, l'API è già abilitata. In caso contrario, fai clic sul pulsante Attiva.

Concedi ruolo IAM al account di servizio

Se stai eseguendo il deployment dell'applicazione sulle risorse Google Cloud e se utilizzi il account di servizio predefinito e non hai modificato le concessioni di ruolo a questo account di servizio, puoi saltare questa sezione.

Se esegui una delle seguenti operazioni, devi concedere all'account di servizio il ruolo IAM Agente Cloud Profiler (roles/cloudprofiler.agent):

  1. Stai utilizzando il account di servizio predefinito, ma hai modificato le concessioni di ruolo.
  2. Stai utilizzando un account di servizio creato dall'utente.
  3. Stai utilizzando Workload Identity, concedi il ruolo Agente Cloud Profiler al account di servizio Kubernetes.

Puoi concedere un ruolo IAM a un account di servizio utilizzando la consoleGoogle Cloud o Google Cloud CLI. Ad esempio, potresti utilizzare il comando gcloud projects add-iam-policy-binding:

gcloud projects add-iam-policy-binding GCP_PROJECT_ID \
    --member serviceAccount:MY_SVC_ACCT_ID@GCP_PROJECT_ID.iam.gserviceaccount.com \
    --role roles/cloudprofiler.agent

Prima di utilizzare il comando precedente, sostituisci quanto segue:

  • GCP_PROJECT_ID: il tuo ID progetto.
  • MY_SVC_ACCT_ID: il nome del account di servizio.

Per informazioni dettagliate, vedi Gestire l'accesso a progetti, cartelle e organizzazioni.

Utilizzo di Cloud Profiler

Per le best practice sull'utilizzo di Python, consulta Configurazione di un ambiente di sviluppo Python.

Compute Engine

Per Compute Engine, segui questi passaggi:

  1. Installa il compilatore C/C++ e gli strumenti di sviluppo:

    sudo apt-get install -y build-essential
    
  2. Installa pip:

    sudo apt-get install -y python3-pip
    
  3. Installa il pacchetto Profiler:

    pip3 install google-cloud-profiler
    
  4. Importa il modulo googlecloudprofiler e chiama la funzione googlecloudprofiler.start il prima possibile nel codice di inizializzazione:

    import googlecloudprofiler
    
    
    def main():
        # Profiler initialization. It starts a daemon thread which continuously
        # collects and uploads profiles. Best done as early as possible.
        try:
            googlecloudprofiler.start(
                service="hello-profiler",
                service_version="1.0.1",
                # verbose is the logging level. 0-error, 1-warning, 2-info,
                # 3-debug. It defaults to 0 (error) if not set.
                verbose=3,
                # project_id must be set if not running on GCP.
                # project_id='my-project-id',
            )
        except (ValueError, NotImplementedError) as exc:
            print(exc)  # Handle errors here

    Devi specificare il parametro service nella funzione start. Per filtrare in base alla versione dell'applicazione nell'interfaccia di Profiler, specifica il parametro service_version. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, vedi Risoluzione dei problemi.

GKE

Per GKE, segui questi passaggi:

  1. Modifica il Dockerfile per installare il pacchetto Profiler:

    FROM python:3
    ...
    RUN apt-get update && apt-get install -y build-essential python3-pip
    RUN pip3 install google-cloud-profiler
    
  2. Importa il modulo googlecloudprofiler e chiama la funzione googlecloudprofiler.start il prima possibile nel codice di inizializzazione:

    import googlecloudprofiler
    
    
    def main():
        # Profiler initialization. It starts a daemon thread which continuously
        # collects and uploads profiles. Best done as early as possible.
        try:
            googlecloudprofiler.start(
                service="hello-profiler",
                service_version="1.0.1",
                # verbose is the logging level. 0-error, 1-warning, 2-info,
                # 3-debug. It defaults to 0 (error) if not set.
                verbose=3,
                # project_id must be set if not running on GCP.
                # project_id='my-project-id',
            )
        except (ValueError, NotImplementedError) as exc:
            print(exc)  # Handle errors here

    Devi specificare il parametro service nella funzione start. Per filtrare in base alla versione dell'applicazione nell'interfaccia di Profiler, specifica il parametro service_version. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, vedi Risoluzione dei problemi.

Ambiente flessibile

Per l'ambiente flessibile di App Engine:

  1. Aggiungi google-cloud-profiler al file requirements.txt.

  2. Importa il modulo googlecloudprofiler e chiama la funzione googlecloudprofiler.start il prima possibile nel codice di inizializzazione.

Per App Engine, service e service_version sono derivati dal tuo ambiente operativo. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, vedi Risoluzione dei problemi.

Ambiente standard

Per l'ambiente standard App Engine, che richiede l'utilizzo dell'ambiente di runtime Python 3, procedi nel seguente modo:

  1. Aggiungi google-cloud-profiler al file requirements.txt.

  2. Importa il modulo googlecloudprofiler e chiama la funzione googlecloudprofiler.start il prima possibile nel codice di inizializzazione.

Per App Engine, service e service_version sono derivati dal tuo ambiente operativo. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, vedi Risoluzione dei problemi.

start funzione

La funzione googlecloudprofiler.start crea un thread daemon che raccoglie e carica continuamente i profili. Devi chiamare start una sola volta e il prima possibile nell'applicazione.

Parametro Descrizione
service1 (Obbligatorio) Il nome del servizio di cui viene eseguito il profiling. Per le limitazioni relative al nome del servizio, vedi Argomenti relativi al nome e alla versione del servizio.
service_version1 (Facoltativo) La versione del servizio di cui viene eseguito il profiling. Per le limitazioni relative alla versione del servizio, consulta Argomenti relativi al nome e alla versione del servizio.
verbose (Facoltativo) Il livello di logging. Per informazioni dettagliate sui livelli di logging, vedi Logging dell'agente.

Il valore predefinito è 0 (Errore).
project_id2 (Facoltativo) L'ID progetto Google Cloud .
disable_cpu_profiling (Facoltativo) Per disattivare la profilazione del tempo CPU, imposta disable_cpu_profiling=True.

Questo parametro è supportato per le versioni di Python da 3.2 a 3.11.0. Per tutte le altre versioni di Python, la profilazione del tempo della CPU non è supportata e questo parametro viene ignorato.

Il valore predefinito è False.
disable_wall_profiling (Facoltativo) Per disattivare la profilazione del muro, imposta disable_wall_profiling=True.

Questo parametro è supportato per le versioni di Python da 3.6 a 3.11.0. Per tutte le altre versioni di Python, la profilazione Wall non è supportata e questo parametro viene ignorato.

Per le limitazioni della funzione start quando è abilitata la profilazione della bacheca, vedi Limitazioni.

Il valore predefinito è False.

1 Solo per Compute Engine e GKE. Per App Engine, il valore deriva dall'ambiente.
2 Per Google Cloud, il valore deriva dall'ambiente. Per gli ambienti nonGoogle Cloud , devi fornire un valore. Per informazioni, vedi Profilazione delle applicazioni in esecuzione all'esterno Google Cloud.

Analisi dei dati

Dopo che Profiler ha raccolto i dati, puoi visualizzarli e analizzarli utilizzando l'interfaccia Profiler.

Nella console Google Cloud , vai alla pagina Profiler:

Vai a Profiler

Puoi trovare questa pagina anche utilizzando la barra di ricerca.

Argomenti del nome e della versione del servizio

Quando carichi l'agente Profiler, specifichi un argomento service-name e un argomento service-version facoltativo per configurarlo.

Il nome del servizio consente a Profiler di raccogliere dati di profilazione per tutte le repliche del servizio. Il servizio di profilazione garantisce una velocità di raccolta di un profilo al minuto, in media, per ogni nome di servizio in ogni combinazione di versioni e zone del servizio.

Ad esempio, se hai un servizio con due versioni in esecuzione su repliche in tre zone, il profiler creerà una media di 6 profili al minuto per quel servizio.

Se utilizzi nomi di servizio diversi per le repliche, il servizio verrà profilato più spesso del necessario, con un overhead corrispondentemente più elevato.

Quando selezioni un nome servizio:

  • Scegli un nome che rappresenti chiaramente il servizio nell'architettura dell'applicazione. La scelta del nome del servizio è meno importante se esegui un solo servizio o applicazione. È più importante se la tua applicazione viene eseguita come un insieme di microservizi, ad esempio.

  • Assicurati di non utilizzare valori specifici del processo, come un ID processo, nella stringa service-name.

  • La stringa service-name deve corrispondere a questa espressione regolare:

    ^[a-z0-9]([-a-z0-9_.]{0,253}[a-z0-9])?$

Una buona linea guida è utilizzare una stringa statica come imageproc-service come nome del servizio.

La versione del servizio è facoltativa. Se specifichi la versione del servizio, Profiler può aggregare le informazioni di profilazione da più istanze e visualizzarle correttamente. Può essere utilizzato per contrassegnare le diverse versioni dei tuoi servizi durante la loro implementazione. L'interfaccia utente di Profiler ti consente di filtrare i dati in base alla versione del servizio, in modo da confrontare il rendimento delle versioni precedenti e più recenti del codice.

Il valore dell'argomento service-version è una stringa in formato libero, ma i valori per questo argomento in genere assomigliano a numeri di versione, ad esempio, 1.0.0 o 2.1.2.

Logging dell'agente

Per impostazione predefinita, l'agente di profilazione registra i messaggi con un livello di gravità error. Per configurare l'agente in modo che registri i messaggi con livelli di gravità inferiori, specifica il parametro verbose quando avvii l'agente. Per verbose sono supportati quattro valori:

  • 0 : Errore
  • 1 : Avviso
  • 2 : Informativo
  • 3 : Debug

Se imposti il parametro verbose su 1 nella chiamata a start, i messaggi con un livello di gravità pari a Warning o Error vengono registrati, mentre i messaggi Informational e Debug vengono ignorati.

Per registrare tutti i messaggi, imposta verbose su 3 all'avvio dell'agente:

googlecloudprofiler.start(service='service_name', verbose=3)

Risoluzione dei problemi

Questa sezione elenca le limitazioni, le eccezioni e i problemi noti specifici per la profilazione delle applicazioni Python. Per assistenza per problemi comuni, consulta la sezione Risoluzione dei problemi.

Limitazioni

Tipo di profilo Limitazioni e restrizioni
Tempo totale di esecuzione
  • Solo profilazione del thread principale.
  • La funzione start del profilo deve essere chiamata dal thread principale.
  • Il gestore dei segnali di Profiler viene eseguito solo sul thread principale. Se il thread principale non può essere eseguito, non vengono acquisiti dati di profilazione.

Eccezioni

Errore Causa Soluzione
NotImplementedError lanciati durante start Applicazione eseguita in un ambiente non Linux.
  • Esegui l'applicazione in un ambiente Linux.
ValueError lanciati durante start Gli argomenti della funzione start non sono validi, non è possibile determinare le informazioni necessarie dalle variabili di ambiente e dagli argomenti o dalla profilazione se la profilazione del tempo della CPU e del tempo reale sono disattivate.
  • Assicurati che il nome e la versione del servizio soddisfino i requisiti definiti in Argomenti nome e versione del servizio.
  • Se la profilazione della parete è abilitata, assicurati che start venga chiamato dal thread principale.
  • Assicurati di utilizzare una versione supportata di Python e che la profilazione del tempo della CPU o del tempo reale sia attivata. Per ulteriori informazioni, vedi la funzione start.
  • Verifica di aver specificato il parametro project_id su start se l'esecuzione avviene al di fuori di Google Cloud. Per saperne di più, consulta la funzione start.

Problemi noti

Comportamento Causa Soluzione
Non hai dati del profilo o hai attivato un nuovo tipo di profilo e mancano i dati del profilo. Le cause più comuni sono correlate alla configurazione. Consulta la sezione Risoluzione dei problemi.
Stai utilizzando uWSGI e non disponi dei dati del profilo relativi al tempo CPU e al tempo reale per tutti i processi.

Quando uWSGI utilizza più worker per gestire le richieste, il comportamento predefinito consiste nell'eseguire l'inizializzazione dell'applicazione solo nel processo principale ("master"). I processi forkati non eseguono la sequenza di inizializzazione.

Se configuri l'agente di profilazione nella sequenza di inizializzazione della tua applicazione, ad esempio in AppConfig.ready() in un'applicazione Django, l'effetto è che l'agente di profilazione non è configurato per i processi fork.

Per eseguire l'inizializzazione dell'applicazione in tutti i processi di lavoro, imposta il flag lazy-apps su true.

Per un problema correlato, consulta l'argomento successivo di questa tabella.

Stai utilizzando uWSGI e non disponi di dati del profilo Wall, ma disponi di dati del profilo del tempo CPU.

Il Profiler di Wall dipende dal modulo di segnali Python. Quando l'interprete Python viene compilato con il supporto dei thread, la configurazione predefinita disattiva la gestione personalizzata dei segnali per i processi forked.

Per le applicazioni uWSGI, attiva la gestione personalizzata dei segnali impostando il flag py-call-osafterfork su true.

Per un problema correlato, consulta l'argomento precedente in questa tabella.

Dopo aver attivato il profiler, il log degli errori contiene nuove voci:

BlockingIOError: [Errno 11] Resource temporarily unavailable Exception ignored when trying to write to the signal wakeup fd

Problema di GitHub

La tua applicazione registrata con il descrittore di file di attivazione del segnale, signal.set_wakeup_fd. Per impostazione predefinita, se il buffer del descrittore di file si riempie, viene registrato un avviso in stderr.

Quando Cloud Profiler raccoglie i profili, attiva segnali con frequenza elevata. Questo comportamento può causare il riempimento del buffer del descrittore di file.

Se la tua applicazione può essere eseguita in sicurezza quando i segnali vengono persi, allora puoi utilizzare Cloud Profiler. Se utilizzi Python 3.7 o versioni successive e vuoi disattivare i messaggi di avviso, passa warn_on_full_buffer=False come parametro a signal.set_wakeup_fd.

Se la tua applicazione non può essere eseguita in sicurezza quando i segnali vengono persi, ti consigliamo di interrompere l'utilizzo di Cloud Profiler. L'uso continuato potrebbe causare la perdita dei numeri di segnale e un numero eccessivo di voci nel log degli errori.

Esecuzione con Linux Alpine

L'agente di profilazione Python per Linux Alpine è supportato solo per le configurazioni di Google Kubernetes Engine.

Per creare l'agente di profilazione Python, devi installare il pacchetto build-base. Per utilizzare l'agente di profilazione Python su Alpine senza installare dipendenze aggiuntive nell'immagine Alpine finale, puoi utilizzare una build in due fasi e compilare l'agente di profilazione Python nella prima fase. Ad esempio, la seguente immagine Docker utilizza una build in più fasi per compilare e installare l'agente di profilazione Python:

FROM python:3.7-alpine as builder

# Install build-base to allow for compilation of the profiling agent.
RUN apk add --update --no-cache build-base

# Compile the profiling agent, generating wheels for it.
RUN pip3 wheel --wheel-dir=/tmp/wheels google-cloud-profiler

FROM python:3.7-alpine

# Copy over the directory containing wheels for the profiling agent.
COPY --from=builder /tmp/wheels /tmp/wheels

# Install the profiling agent.
RUN pip3 install --no-index --find-links=/tmp/wheels google-cloud-profiler

# Install any other required modules or dependencies, and copy an app which
# enables the profiler as described in "Enable the profiler in your
# application".
COPY ./bench.py .

# Run the application when the docker image is run, using either CMD (as is done
# here) or ENTRYPOINT.
CMD python3 -u bench.py

Errore di autenticazione

Se utilizzi immagini Docker eseguite con Linux Alpine (ad esempio golang:alpine o semplicemente alpine), potresti visualizzare il seguente errore di autenticazione:

connection error: desc = "transport: authentication handshake failed: x509: failed to load system roots and no roots provided"

Tieni presente che per visualizzare l'errore devi aver attivato la registrazione dell'agente.

L'errore indica che le immagini Docker con Linux Alpine non hanno i certificati SSL root installati per impostazione predefinita. Questi certificati sono necessari perché l'agente di profilazione comunichi con l'API Profiler. Per risolvere questo errore, aggiungi il seguente comando apk al Dockerfile:

FROM alpine
...
RUN apk add --no-cache ca-certificates

Dopodiché, devi ricompilare e ridistribuire l'applicazione.

Passaggi successivi