Profilerstellung für Python-Code

Auf dieser Seite wird beschrieben, wie Sie Ihre Python-Anwendung so ändern, dass Datenprofile erstellt und an Ihr Google Cloud-Projekt gesendet werden können. Allgemeine Informationen zur Profilerstellung finden Sie unter Konzepte der Profilerstellung.

Profiltypen für Python:

  • CPU-Zeit
  • Echtzeit (Hauptthread)

Unterstützte Python-Sprachversionen:

  • Python 3.6 oder höher

Unterstützte Profiler-Agent-Versionen:

  • Der neueste Release des Agents wird unterstützt. Im Allgemeinen werden Releases, die älter als ein Jahr sind, nicht unterstützt. Wir empfehlen, die neueste veröffentlichte Version des Agents zu verwenden.

Unterstützte Betriebssysteme:

  • Linux: Die Profilerstellung für Python-Anwendungen wird für Linux-Kernel unterstützt, deren Standard-C-Bibliothek mit glibc oder musl implementiert wurde. Konfigurationsinformationen zu Linux Alpine-Kernels finden Sie unter Mit Linux Alpine ausführen.

Unterstützte Umgebungen:

Profiler API aktivieren

Sorgen Sie vor Verwendung des Profiler-Agents dafür, dass die zugrunde liegende Profiler API aktiviert ist. Sie können den Status der API prüfen und sie bei Bedarf über die Google Cloud-Befehlszeile oder die Google Cloud Console aktivieren:

gcloud-CLI

  1. Wenn Sie die Google Cloud-Befehlszeile noch nicht auf Ihrer Workstation installiert haben, lesen Sie die Dokumentation zur Google Cloud-Befehlszeile.

  2. Führen Sie dazu diesen Befehl aus:

    gcloud services enable cloudprofiler.googleapis.com
    

Weitere Informationen finden Sie unter gcloud services.

Google Cloud Console

  1. Enable the required API.

    Enable the API

  2. Wenn API aktiviert angezeigt wird, ist die API bereits aktiviert. Falls nicht, klicken Sie auf die Schaltfläche Aktivieren.

Cloud Profiler verwenden

Best Practices für die Verwendung von Python finden Sie unter Python-Entwicklungsumgebung einrichten.

Compute Engine

Führen Sie für Compute Engine folgende Schritte aus:

  1. Installieren Sie den C/C++-Compiler und die Entwicklungstools:

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

    sudo apt-get install -y python3-pip
    
  3. Installieren Sie das Profiler-Paket:

    pip3 install google-cloud-profiler
    
  4. Importieren Sie das Modul googlecloudprofiler und rufen Sie die Funktion googlecloudprofiler.start so früh wie möglich in Ihrem Initialisierungscode auf:

    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

    Sie müssen den Parameter service in Ihrer start-Funktion angeben. Geben Sie außerdem den Parameter service_version an, damit auf der Profiler-Oberfläche nach der Anwendungsversion gefiltert werden kann. Weitere Informationen zur Fehlerbehebung und zu Ausnahmen finden Sie unter Fehlerbehebung.

GKE

Führen Sie für GKE die folgenden Schritte aus:

  1. Ändern Sie das Dockerfile so, dass das Profiler-Paket installiert wird:

    FROM python:3
    ...
    RUN apt-get update && apt-get install -y build-essential python3-pip
    RUN pip3 install google-cloud-profiler
    
  2. Importieren Sie das Modul googlecloudprofiler und rufen Sie die Funktion googlecloudprofiler.start so früh wie möglich in Ihrem Initialisierungscode auf:

    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

    Sie müssen den Parameter service in Ihrer start-Funktion angeben. Geben Sie außerdem den Parameter service_version an, damit auf der Profiler-Oberfläche nach der Anwendungsversion gefiltert werden kann. Weitere Informationen zur Fehlerbehebung und zu Ausnahmen finden Sie unter Fehlerbehebung.

Flexible Umgebung

Führen Sie für die flexible App Engine-Umgebung folgende Schritte aus:

  1. Fügen Sie google-cloud-profiler zu Ihrer Datei requirements.txt hinzu.

  2. Importieren Sie das Modul googlecloudprofiler und rufen Sie die Funktion googlecloudprofiler.start so früh wie möglich in Ihrem Initialisierungscode auf.

Bei App Engine werden service und service_version aus Ihrer Betriebsumgebung abgeleitet. Weitere Informationen zur Fehlerbehebung und zu Ausnahmen finden Sie unter Fehlerbehebung.

Standardumgebung

Führen Sie für die App Engine-Standardumgebung die nachfolgenden Schritte aus, wobei die Python 3-Laufzeitumgebung erforderlich ist:

  1. Fügen Sie google-cloud-profiler zu Ihrer Datei requirements.txt hinzu.

  2. Importieren Sie das Modul googlecloudprofiler und rufen Sie die Funktion googlecloudprofiler.start so früh wie möglich in Ihrem Initialisierungscode auf.

Bei App Engine werden service und service_version aus Ihrer Betriebsumgebung abgeleitet. Weitere Informationen zur Fehlerbehebung und zu Ausnahmen finden Sie unter Fehlerbehebung.

start-Funktion

Die Funktion googlecloudprofiler.start erstellt einen Daemon-Thread, der kontinuierlich Profile erfasst und hochlädt. Rufen Sie start ein einziges Mal und so früh wie möglich in Ihrer Anwendung auf.

Parameter Beschreibung
service1 (Erforderlich) Der Name des Dienstes, für den ein Profil erstellt wird. Informationen zu Einschränkungen für den Dienstnamen finden Sie unter Argumente für Dienstnamen und -versionen.
service_version1 (Optional) Die Version des Dienstes, für den ein Profil erstellt wird. Informationen zu Einschränkungen für die Dienstversion finden Sie unter Argumente für Dienstnamen und -versionen.
verbose (Optional) Die Logging-Ebene. Genauere Angaben zu den Logging-Ebenen finden Sie unter Agent-Logging.

Der Standardwert ist 0 (Fehler).
project_id2 (Optional) Ihre Google Cloud-Projekt-ID.
disable_cpu_profiling (Optional) Zum Deaktivieren von CPU-Zeitprofilen legen Sie disable_cpu_profiling=True fest.

Dieser Parameter wird nur ab Python Version 3.2 unterstützt. Bei allen anderen Python-Versionen wird das Erstellen von CPU-Zeitprofilen nicht unterstützt und dieser Parameter wird ignoriert.

Der Standardwert ist False.
disable_wall_profiling (Optional) Zum Deaktivieren von Echtzeitprofilen legen Sie disable_wall_profiling=True fest.

Dieser Parameter wird für Python 3.6 und höher unterstützt. Bei allen anderen Python-Versionen wird das Erstellen von Echtzeitprofilen nicht unterstützt und dieser Parameter ignoriert.

Einschränkungen für die Funktion start bei aktivierten Echtzeitprofilen finden Sie unter Einschränkungen.

Der Standardwert ist False.

1 Nur für Compute Engine und GKE. Bei App Engine wird der Wert aus der Umgebung abgeleitet.
2 Bei Google Cloud wird der Wert aus der Umgebung abgeleitet. Für alle anderen Umgebungen müssen Sie einen Wert angeben. Weitere Informationen finden Sie unter Profilerstellung für Code außerhalb der Google Cloud Platform.

Daten analysieren

Nachdem Profiler Daten erfasst hat, können Sie diese mit der Profiler-Oberfläche ansehen und analysieren.

Rufen Sie in der Google Cloud Console die Seite Profiler auf:

Gehen Sie zum Profiler.

Sie können diese Seite auch über die Suchleiste finden.

Argumente für Dienstnamen und -versionen

Wenn Sie den Profiler-Agent laden, geben Sie zu dessen Konfiguration ein Argument für den Dienstnamen und ein optionales Argument für die Dienstversion an.

Profiler kann Daten für alle Replikate des unter Dienstname angegebenen Dienstes erfassen. Der Profiler-Dienst hat eine durchschnittliche Erfassungsrate von einem Profil pro Minute für jede Kombination aus Dienstversion und Zone jedes Dienstnamens.

Beispielsweise erstellt Profiler für einen Dienst mit zwei Versionen, dessen Replikate in drei Zonen ausgeführt werden, durchschnittlich sechs Profile pro Minute.

Wenn Sie für die Replikate unterschiedliche Dienstnamen verwenden, werden Dienstprofile häufiger als nötig mit einem entsprechend höheren Overhead erstellt.

Berücksichtigen Sie beim Auswählen eines Dienstnamens Folgendes:

  • Wählen Sie einen Namen aus, der den Dienst in Ihrer Anwendungsarchitektur klar darstellt. Wenn Sie nur einen einzigen Dienst oder eine einzige Anwendung ausführen, spielt der Dienstname eine untergeordnete Rolle. Er gewinnt aber an Bedeutung, wenn Ihre Anwendung beispielsweise in Form mehrerer Mikrodienste ausgeführt wird.

  • Achten Sie darauf, keine prozessspezifischen Werte wie eine Prozess-ID im String für den Dienstnamen zu verwenden.

  • Der String für den Dienstnamen muss diesem regulären Ausdruck entsprechen:

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

Es empfiehlt sich, einen statischen String wie imageproc-service als Dienstnamen zu verwenden.

Die Dienstversion ist optional. Wenn Sie die Dienstversion angeben, kann Profiler Profilinformationen aus mehreren Instanzen aggregieren und korrekt anzeigen. Sie können so verschiedene Versionen Ihrer Dienste kennzeichnen, wenn diese bereitgestellt werden. Die Profiler-Oberfläche ermöglicht Ihnen, die Daten nach Dienstversion zu filtern. So können Sie die Leistung von älteren und neueren Versionen des Codes vergleichen.

Obwohl der Wert des Dienstversionsarguments ein Freitextstring ist, sehen die Werte für dieses Argument meist wie Versionsnummern aus, zum Beispiel 1.0.0 oder 2.1.2.

Agent-Logging

Standardmäßig speichert der Profiler-Agent Meldungen mit der Wichtigkeitsstufe error in Logs. Wenn der Agent Meldungen mit niedrigeren Wichtigkeitsstufen in Logs speichern soll, geben Sie den Parameter verbose beim Starten des Agents an. Für verbose werden vier Werte unterstützt:

  • 0: Error
  • 1: Warning
  • 2: Informational
  • 3: Debug

Wenn Sie im Aufruf von start den Parameter verbose auf 1 festlegen, werden Meldungen mit einer Wichtigkeitsstufe von Warning oder Error in Logs gespeichert und Meldungen mit Informational und Debug ignoriert.

Damit alle Meldungen in Logs gespeichert werden, legen Sie verbose beim Starten des Agents auf 3 fest:

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

Fehlerbehebung

In diesem Abschnitt werden Einschränkungen, Ausnahmen und bekannte Probleme aufgeführt, die speziell bei der Profilerstellung für Python-Anwendungen auftreten. Informationen zu häufig auftretenden Problemen finden Sie unter Fehlerbehebung.

Beschränkungen

Profiltyp Beschränkungen
Echtzeit
  • Profilerstellung nur für Hauptthreads.
  • Die Funktion start für das Profil muss vom Hauptthread aus aufgerufen werden.
  • Der Signal-Handler von Profiler wird nur für den Hauptthread ausgeführt. Wenn der Hauptthread nicht ausgeführt werden kann, werden keine Profildaten erfasst.

Ausnahmen

Fehler Ursache Lösung
Während start wird NotImplementedError ausgelöst. Die Anwendung wird nicht in einer Linux-Umgebung ausgeführt.
  • Führen Sie Ihre Anwendung in einer Linux-Umgebung aus.
Während start wird ValueError ausgelöst. Die Argumente der Funktion start sind ungültig, notwendige Informationen können nicht aus den Umgebungsvariablen und -argumenten abgeleitet werden oder bei der Profilerstellung sind sowohl CPU-Zeitprofile als auch Echtzeitprofile deaktiviert.
  • Prüfen Sie, ob der Name und die Version des Dienstes die unter Argumente für Dienstnamen und -versionen definierten Anforderungen erfüllen.
  • Wenn das Erstellen von Echtzeitprofilen aktiviert ist, sorgen Sie dafür, dass start vom Hauptthread aus aufgerufen wird.
  • Prüfen Sie, ob Sie eine unterstützte Version von Python verwenden und ob die Erstellung von CPU-Zeitprofilen bzw. Echtzeitprofilen aktiviert ist. Weitere Informationen finden Sie unter start-Funktion.
  • Prüfen Sie, ob Sie den Parameter project_id auf start festgelegt haben, wenn Sie die Anwendung außerhalb der GCP ausführen. Weitere Informationen finden Sie unter start-Funktion.

Bekannte Probleme

Verhalten Ursache Lösung
Sie haben keine Profildaten oder haben einen neuen Profiltyp aktiviert und es fehlen Profildaten. Häufige Ursachen hängen mit der Konfiguration zusammen. Weitere Informationen erhalten Sie im Abschnitt zur Fehlerbehebung.
Sie verwenden uWSGI und haben nicht für alle Prozesse CPU-Zeit- und Wall-Profildaten.

Wenn uWSGI mehrere Worker zur Verarbeitung von Anfragen verwendet, wird die Anwendungsinitialisierung standardmäßig nur im Primärprozess (Masterprozess) durchgeführt. Die verzweigten Prozesse führen die Initialisierungssequenz nicht aus.

Wenn Sie den Profiler-Agent in der Initialisierungssequenz Ihrer Anwendung konfigurieren, z. B. in einer Django-Anwendung in AppConfig.ready(), hat dies zur Folge, dass der Profiler-Agent nicht für die verzweigten Prozesse konfiguriert wird.

Setzen Sie das Flag lazy-apps auf true, um die Anwendungsinitialisierung in allen Worker-Prozessen durchzuführen

Ein ähnliches Problem finden Sie im nächsten Thema dieser Tabelle.

Sie verwenden uWSGI und haben keine Wall-Profildaten, aber CPU-Zeitprofildaten.

Der Wall-Profiler hängt vom Python-Signalmodul ab. Wenn der Python-Interpreter mit Threadunterstützung kompiliert wird, deaktiviert die Standardkonfiguration die benutzerdefinierte Signalverarbeitung für verzweigte Prozesse.

Aktivieren Sie für uWSGI-Anwendungen die benutzerdefinierte Signalverarbeitung, indem Sie das Flag py-call-osafterfork auf true setzen.

Ein ähnliches Problem finden Sie im vorherigen Thema dieser Tabelle.

Nach Aktivierung von Profiler enthält das Fehlerlog neue Einträge:

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

GitHub-Problem

Ihre Anwendung, die mit dem Signal-Wakeup-Dateideskriptor signal.set_wakeup_fd registriert ist. Wenn der Zwischenspeicher der Dateibeschreibung gefüllt wird, wird standardmäßig eine Warnung in stderr protokolliert.

Wenn Cloud Profiler Profile erfasst, werden Signale mit hoher Frequenz ausgelöst. Dieses Verhalten kann dazu führen, dass der Puffer des Dateideskriptors voll wird.

Wenn Ihre Anwendung bei einem Verlust von Signalen sicher ausgeführt werden kann, können Sie Cloud Profiler verwenden. Wenn Sie Python 3.7 oder höher verwenden und die Warnmeldungen deaktivieren möchten, übergeben Sie warn_on_full_buffer=False als Parameter an signal.set_wakeup_fd.

Wenn Ihre Anwendung bei einem Verlust von Signalen nicht sicher ausgeführt werden kann, sollten Sie Cloud Profiler nicht mehr verwenden. Eine weitere Verwendung kann den Verlust von Signalnummern und übermäßige Einträge im Fehlerlog nach sich ziehen.

Mit Linux Alpine ausführen

Der Python-Profiler-Agent für Linux Alpine wird nur für Google Kubernetes Engine-Konfigurationen unterstützt.

Zum Erstellen des Python-Profiler-Agents müssen Sie das Paket build-base installieren. Wenn Sie den Python-Profiler-Agent auf Alpine verwenden möchten, ohne zusätzliche Abhängigkeiten für das endgültige Alpine-Image zu installieren, können Sie den Python-Profiler-Agent in der ersten Phase erstellen und kompilieren. Beim folgenden Docker-Image wird beispielsweise ein mehrstufiger Build verwendet, um den Python-Profiler-Agent zu kompilieren und zu installieren:

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

Authentifizierungsfehler

Wenn Sie Docker-Images wie golang:alpine oder nur alpine verwenden, die mit Linux Alpine ausgeführt werden, wird möglicherweise der folgende Authentifizierungsfehler angezeigt:

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

Der Fehler ist nur sichtbar, wenn Agent-Logging aktiviert ist.

Der Fehler zeigt an, dass die Root-SSL-Zertifikate für die Docker-Images mit Linux Alpine nicht standardmäßig installiert sind. Diese Zertifikate sind erforderlich, damit der Profiler-Agent mit der Profiler API kommunizieren kann. Fügen Sie Ihrem Dockerfile den folgenden apk-Befehl hinzu, um diesen Fehler zu beheben:

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

Sie müssen dann Ihre Anwendung neu erstellen und noch einmal bereitstellen.

Nächste Schritte