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, consulta Concetti di profilazione.

Tipi di profilo per Python:

  • Tempo CPU
  • Tempo di esecuzione (thread principale)

Versioni del linguaggio Python supportate:

  • Python 3.6 o versioni successive.

Versioni dell'agente di profilazione supportate:

  • È supportata la release più recente dell'agente. In genere, le release che risalgono a più di un anno fa non sono supportate. Ti consigliamo di utilizzare la versione rilasciata più recente dell'agente.

Sistemi operativi supportati:

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

Ambienti supportati:

Abilitazione 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 già 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 maggiori informazioni, consulta gcloud services.

Console Google Cloud

  1. Nel pannello di navigazione della console Google Cloud, seleziona API e servizi, fai clic su Abilita API e servizi e poi abilita l'API Cloud Profiler:

    Vai alle impostazioni dell'API Profiler

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

Utilizzo di Cloud Profiler

Per le best practice relative all'utilizzo di Python, consulta la pagina Configurare un ambiente di sviluppo Python.

Compute Engine

Per Compute Engine, segui questi passaggi:

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

    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 Profiler, specifica il parametro service_version. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, consulta la sezione Risoluzione dei problemi.

GKE

Per GKE, segui questi passaggi:

  1. Modifica il tuo 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 Profiler, specifica il parametro service_version. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, consulta la sezione Risoluzione dei problemi.

Ambiente flessibile

Per l'ambiente flessibile di App Engine, segui questi passaggi:

  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 dall'ambiente operativo. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, consulta la sezione Risoluzione dei problemi.

Ambiente standard

Per l'ambiente standard di App Engine, che richiede l'utilizzo dell'ambiente di runtime Python 3, segui questi passaggi:

  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 dall'ambiente operativo. Per informazioni sulla risoluzione dei problemi e sulle eccezioni, consulta la sezione Risoluzione dei problemi.

start funzione

La funzione googlecloudprofiler.start crea un thread del daemon che raccoglie e carica continuamente profili. Devi chiamare start una volta e il prima possibile nella richiesta di partecipazione.

Parametro Descrizione
service1 (Obbligatorio) Il nome del servizio profilato. Per le limitazioni sul nome del servizio, consulta Argomenti della versione e del nome del servizio.
service_version1 (Facoltativo) La versione del servizio che stai profilando. Per le limitazioni sulla versione del servizio, consulta Argomenti della versione e del nome del servizio.
verbose (Facoltativo) Livello di logging. Per maggiori dettagli sui livelli di logging, consulta Logging degli agenti.

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

Questo parametro è supportato solo per Python 3.2 e versioni successive. Per tutte le altre versioni Python, la profilazione del tempo di 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 Python 3.6 e versioni successive. Per tutte le altre versioni Python, la profilazione del wall non è supportata e questo parametro viene ignorato.

Per le limitazioni della funzione start quando la profilazione del muro è abilitata, consulta 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 non Google Cloud, devi fornire un valore. Per informazioni, consulta Profilazione delle applicazioni in esecuzione al di fuori di Google Cloud.

Analisi dei dati

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

Nel pannello di navigazione della console Google Cloud, seleziona Profiler:

Vai a Profiler

Argomenti della versione e del nome del servizio

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

Il nome del servizio consente a Profiler di raccogliere i dati di profilazione per tutte le repliche di quel servizio. Il servizio profiler garantisce una frequenza di raccolta di un profilo al minuto, in media, per ciascun nome di servizio in ogni combinazione di versioni e zone di 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 maggiore.

Quando selezioni il nome di un 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 una singola applicazione. Ad esempio, è più importante se l'applicazione viene eseguita come un insieme di micro-servizi.

  • Assicurati di non utilizzare valori specifici del processo, come un ID processo, nella stringa del nome del servizio.

  • La stringa del nome del servizio deve corrispondere alla seguente espressione regolare:

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

Una buona linea guida è quella di 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 usata per contrassegnare le diverse versioni dei servizi man mano che ne viene eseguito il deployment. L'interfaccia utente di Profiler ti consente di filtrare i dati in base alla versione del servizio, in modo da confrontare le prestazioni 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 solitamente sono come numeri di versione, ad esempio 1.0.0 o 2.1.2.

Logging degli agenti

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 all'avvio dell'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à 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 limitazioni, eccezioni e problemi noti specifici della profilazione delle applicazioni Python. Per assistenza in caso di problemi comuni, consulta la sezione Risoluzione dei problemi.

Limitazioni

Tipo di profilo Limitazioni e limitazioni
Tempo totale di esecuzione
  • Solo profilazione del thread principale.
  • La funzione del profilo start deve essere chiamata dal thread principale.
  • Il gestore degli indicatori Profiler viene eseguito solo sul thread principale. Se non è possibile eseguire il thread principale, non vengono acquisiti dati di profilazione.

Eccezioni

Errore Causa Soluzione
NotImplementedError lanciati durante start Applicazione eseguita in un ambiente non Linux.
  • Eseguire l'applicazione in un ambiente Linux.
ValueError lanciati durante start Gli argomenti della funzione start non sono validi. Non è possibile determinare le informazioni necessarie a partire dalle variabili di ambiente e dagli argomenti o dalla profilazione se sia la profilazione del tempo di CPU sia quella del tempo di esecuzione sono disabilitate.
  • Assicurati che il nome e la versione del servizio soddisfino i requisiti definiti in Argomenti della versione e del nome del servizio.
  • Se la profilazione del muro è abilitata, assicurati che start venga chiamato dal thread principale.
  • Assicurati di utilizzare una versione supportata di Python e che la profilazione del tempo di CPU o del tempo di esecuzione sia abilitata. Per maggiori informazioni, consulta Funzione start.
  • Verifica di aver specificato il parametro project_id per start se l'esecuzione avviene al di fuori di Google Cloud. Per maggiori informazioni, consulta la sezione Funzione start.

Problemi noti

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

Quando uWSGI utilizza più worker per gestire le richieste, il comportamento predefinito prevede di eseguire l'inizializzazione dell'applicazione solo nel processo primario ("master"). I processi creati con fork non eseguono la sequenza di inizializzazione.

Se configuri l'agente di profilazione nella sequenza di inizializzazione dell'applicazione, ad esempio in AppConfig.ready() in un'applicazione Django, l'agente di profilazione non è configurato per i processi di cui è stato eseguito il fork.

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

Consulta l'argomento successivo di questa tabella per un problema correlato.

Stai utilizzando uWSGI e non hai dati del profilo Wall, ma hai dati del profilo relativi al tempo di CPU.

Il profiler del Wall dipende dal modulo del segnale Python. Quando l'interprete Python viene compilato con il supporto dei thread, la configurazione predefinita disabilita la gestione degli indicatori personalizzati per i processi di cui è stato eseguito il fork.

Per le applicazioni uWSGI, abilita la gestione degli indicatori personalizzati impostando il flag py-call-osafterfork su true.

Consulta l'argomento precedente di questa tabella per un problema correlato.

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 GitHub

L'applicazione è stata registrata con il descrittore del file di wakeup dell'indicatore, signal.set_wakeup_fd. Per impostazione predefinita, se il buffer del descrittore del file si riempie, viene registrato un avviso in stderr.

Quando Cloud Profiler raccoglie i profili, attiva gli indicatori con alta frequenza. Questo comportamento può causare l'esaurimento del buffer del descrittore del file.

Se la tua applicazione può essere eseguita in modo sicuro quando gli indicatori vengono persi, puoi utilizzare Cloud Profiler. Se utilizzi Python 3.7 o versioni successive e vuoi disabilitare 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 modo sicuro quando gli indicatori vengono persi, ti consigliamo di interrompere l'utilizzo di Cloud Profiler. L'uso continuato potrebbe causare la perdita dei numeri di indicatori 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 sull'immagine Alpine finale, puoi utilizzare una build a due fasi e compilare l'agente di profilazione Python nella prima fase. Ad esempio, la seguente immagine Docker utilizza una build multi-fase 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 solo 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 avere abilitato il logging degli agenti.

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

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

Poi devi ricreare l'applicazione ed eseguirne nuovamente il deployment.

Passaggi successivi