Python アプリケーションのプロファイリング

このページでは、プロファイリング データを収集し、そのデータを Google Cloud Platform(GCP)プロジェクトに送信するように Python アプリケーションを変更する方法について説明します。プロファイリングの全般的な情報については、プロファイリングのコンセプトをご覧ください。

Python のプロファイル タイプ:

  • CPU 時間
  • 経過時間(メインスレッド、Python 3.6 以降が必要)

サポートされている Python 言語バージョン:

  • Python 3.2 以降

サポートされているオペレーティング システム:

  • 標準 C ライブラリが glibc で実装されている Linux バージョン。

サポートされる環境:

Profiler API を有効にする

プロファイリング エージェントを使用する前に、基盤となる Profiler API が有効になっている必要があります。Cloud SDK gcloud コマンドライン ツールまたは Cloud Console で API のステータスを確認し、無効になっている場合は有効にしてください。

Cloud SDK

  1. ワークステーションに Cloud SDK がまだインストールされていない場合は、Google Cloud SDK をご覧ください。

  2. 次のコマンドを実行します。

    gcloud services enable cloudprofiler.googleapis.com
    

詳細については、gcloud services をご覧ください。

Cloud Console

  1. [API とサービス] ダッシュボードに移動します。

    [API とサービス] に移動

  2. API へのアクセスで使用するプロジェクトを選択します。

  3. [API とサービスを追加] ボタンをクリックします。

    API とサービスの追加

  4. Profiler API を検索します。

  5. 検索結果で、Stackdriver Profiler API を選択します。

  6. [API が有効です] が表示されている場合、API はすでに有効になっています。そうでない場合は、[有効にする] ボタンをクリックします。

Stackdriver Profiler を使用する

Python の使用に関するおすすめの方法については、Python 開発環境の設定をご覧ください。

Compute Engine

Compute Engine の場合は、次の操作を行います。

  1. C/C++ コンパイラとデベロッパー ツールをインストールします。

    sudo apt-get install -y build-essential
    
  2. pip をインストールします。

    sudo apt-get install -y python3-pip
    
  3. Profiler パッケージをインストールします。

    pip3 install google-cloud-profiler
    
  4. 初期化コードのできるだけ早い段階で googlecloudprofiler パッケージをインポートし、googlecloudprofiler.start 関数を呼び出します。

    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

    start 関数に service パラメータを指定する必要があります。Profiler インターフェースで、アプリケーションのバージョンをフィルタにするには、service_version パラメータを指定します。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。

GKE

GKE の場合は、次の操作を行います。

  1. Dockerfile を変更して Profiler パッケージをインストールします。

    FROM python:3
    ...
    RUN apt-get update && apt-get install -y build-essential python3-pip
    RUN pip3 install google-cloud-profiler
    
  2. 初期化コードのできるだけ早い段階で googlecloudprofiler パッケージをインポートし、googlecloudprofiler.start 関数を呼び出します。

    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

    start 関数に service パラメータを指定する必要があります。Profiler インターフェースで、アプリケーションのバージョンをフィルタにするには、service_version パラメータを指定します。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。

フレキシブル環境

App Engine フレキシブル環境の場合は、次の操作を行います。

  1. google-cloud-profilerrequirements.txt ファイルに追加します。

  2. 初期化コードのできるだけ早い段階で googlecloudprofiler パッケージをインポートし、googlecloudprofiler.start 関数を呼び出します。

    import googlecloudprofiler
    
    # Profiler initialization. It starts a daemon thread which continuously
    # collects and uploads profiles. Best done as early as possible.
    try:
        # service and service_version can be automatically inferred when
        # running on App Engine. project_id must be set if not running
        # on GCP.
        googlecloudprofiler.start(verbose=3)
    except (ValueError, NotImplementedError) as exc:
        print(exc)  # Handle errors here
    

App Engine の場合、serviceservice_version はオペレーション環境から取得されます。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。

スタンダード環境

App Engine スタンダード環境の場合は、Python 3 ランタイム環境を使用する必要があります。次の操作を行います。

  1. google-cloud-profilerrequirements.txt ファイルに追加します。

  2. 初期化コードのできるだけ早い段階で googlecloudprofiler パッケージをインポートし、googlecloudprofiler.start 関数を呼び出します。

    import googlecloudprofiler
    
    # Profiler initialization. It starts a daemon thread which continuously
    # collects and uploads profiles. Best done as early as possible.
    try:
        # service and service_version can be automatically inferred when
        # running on App Engine. project_id must be set if not running
        # on GCP.
        googlecloudprofiler.start(verbose=3)
    except (ValueError, NotImplementedError) as exc:
        print(exc)  # Handle errors here
    

App Engine の場合、serviceservice_version はオペレーション環境から取得されます。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。

start 関数

googlecloudprofiler.start 関数は、プロファイルを継続的に収集してアップロードするデーモン スレッドを作成します。アプリケーションのできるだけ早い段階で start を 1 回呼び出す必要があります。

パラメータ 説明
service1 (必須)プロファイリングされるサービスの名前。サービス名の制限については、サービス名とバージョンの引数をご覧ください。
service_version1 (省略可)プロファイリングされるサービスのバージョン。サービスのバージョンに関する制限については、サービス名とバージョンの引数をご覧ください。
verbose (省略可)ロギングレベル。ロギングレベルの詳細については、エージェント ロギングをご覧ください。

デフォルト値は 0(エラー)です。
project_id2 (省略可)GCP プロジェクトの ID。
disable_cpu_profiling (省略可)CPU プロファイリングを無効にするには、disable_cpu_profiling=True を設定します。

このパラメータは、Python バージョン 3.2 以降でのみサポートされます。他のバージョンの Python の場合、CPU プロファイリングはサポートされていないため、このパラメータは無視されます。

デフォルト値は False です。
disable_wall_profiling (省略可)経過時間プロファイリングを無効にするには、disable_wall_profiling=True を設定します。

このパラメータは、Python 2 と Python 3.6 以降でサポートされます。他のバージョンの Python の場合、経過時間プロファイリングはサポートされていないため、このパラメータは無視されます。

経過時間プロファイリングが有効な場合の start 関数の制限については、制限事項をご覧ください。

デフォルト値は False です。

1 Compute Engine と GKE の場合にのみ利用可能です。App Engine の場合、この値は環境から取得されます。
2 GCP の場合、この値は環境から取得されます。GCP 以外の環境では、値を設定する必要があります。詳細については、Google Cloud Platform の外部で実行されているアプリケーションのプロファイリングをご覧ください。

データの分析

Profiler が収集したデータを Profiler のインターフェースに表示し、分析できます。このインターフェースの開始方法については、Profiler インターフェースを開くをご覧ください。

サービス名とバージョンの引数

Profiler エージェントを読み込むときに、service-name 引数とオプションの service-version 引数を指定して構成します。

Profiler は、サービス名で指定されたサービスのすべてのレプリカからプロファイリング データを収集します。Profiler サービスは、サービス バージョンとゾーンの組み合わせに対して、1 つのサービス名について平均で 1 分あたり 1 個のプロファイルを作成します。

たとえば、1 つのサービスの 2 つのバージョンが 3 つのゾーンのレプリカで実行されている場合、Profiler はそのサービスについて 1 分あたり平均で 6 個のプロファイルを作成します。

レプリカで異なるサービス名を使用している場合、サービスが必要以上にプロファイリングされるため、オーバーヘッドが大きくなります。

サービス名を選択する場合は、次の点に注意してください。

  • アプリケーション アーキテクチャでサービスを明確に識別できる名前を選択してください。1 つのサービスまたはアプリケーションしか実行していない場合は、どのようなサービス名を選択するかはさほど問題になりません。しかし、アプリケーションが一連のマイクロサービスとして実行されている場合は、名前の選択は重要になります。

  • service-name 文字列で、プロセス ID などのプロセス固有の値を使用しないでください。

  • service-name 文字列は次の正規表現と一致する必要があります。

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

サービス名として imageproc-service のような静的文字列を使用することをおすすめします。

サービス バージョンは省略可能です。サービス バージョンを指定すると、複数のインスタンスからプロファイリング情報が集約され、バージョンごとに表示されます。これは、複数のバージョンがデプロイされているときの識別に役立ちます。Profiler UI では、データをサービス バージョンでフィルタできます。これにより、コードの新旧バージョンのパフォーマンスを比較できます。

service-version 引数には、自由形式の文字列を指定できますが、通常は、バージョン番号のような値を使用します(例: 1.0.02.1.2)。

エージェント ロギング

デフォルトでは、プロファイリング エージェントは重大度が error のメッセージをログに記録します。より低い重大度のメッセージをログに記録するようにエージェントを構成するには、エージェントの起動時に verbose パラメータを指定します。verbose に指定できる値は次の 4 つです。

  • 0 : エラー
  • 1 : 警告
  • 2 : 情報
  • 3 : デバッグ

start の呼び出しで verbose パラメータに 1 を設定すると、重大度が Warning または Error のメッセージがログに記録され、InformationalDebug のメッセージは無視されます。

すべてのメッセージをログに記録するには、エージェントの起動時に verbose3 に設定します。

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

トラブルシューティング

このセクションでは、制限事項、例外、既知の問題について説明します。

制限事項

プロファイルの種類 制限事項
CPU 時間
  • Python 3.2 以降でサポートされます。
経過時間
  • Python 3.6 以降でサポートされます。
  • Python 3.0 から 3.5 では利用できません。
  • Python 2 で利用できますが、サポート対象外です。
  • メインスレッド プロファイリングのみ。
  • プロファイルの start 関数をメインスレッドから呼び出す必要があります。
  • Profiler シグナル ハンドラはメインスレッドでのみ実行されます。メインスレッドが実行できない場合、プロファイリング データは収集されません。

例外

エラー 原因 解決方法
startNotImplementedError がスローされる アプリケーションが Linux 以外の環境で実行されています。
  • アプリケーションを Linux 環境で実行します。
startValueError がスローされる start 関数の引数が無効です。環境変数と引数から必要な情報を特定できません。CPU プロファイリングと経過時間プロファイリングの両方が無効になっているときに、プロファイリングが実行されました。
  • サービス名とバージョンが、サービス名とバージョンの引数で定義されている要件を満たしていることを確認します。
  • 経過時間プロファイリングが有効になっている場合は、start がメインスレッドから呼び出されるようにします。
  • サポートされているバージョンの Python を使用し、CPU プロファイリングまたは経過時間プロファイリングが有効になっていることを確認します。詳細については、start 関数をご覧ください。
  • GCP の外部でプログラムを実行している場合は、project_id パラメータに start が指定されていることを確認します。詳細については、start 関数をご覧ください。

既知の問題

動作 原因 解決方法
CPU または経過時間をプロファイリングすると、Python 3.4 以前のアプリケーションでシステム呼び出しが失敗します。 バージョン 3.4 以前の Python では、EINTR シグナルによってシステム呼び出しが中断されます。アプリケーションがこのシナリオに対応している必要があります。詳細については、PEP 475 をご覧ください。
  • Python 3.5 以降を使用します。
  • アプリケーションで EINTR レスポンス コードを処理します。
経過時間プロファイリングが有効になっていると、Python 3.5 以前のアプリケーションがシグナルに応答しません。 Python 3.5 以前ではシグナルの処理で競合条件が発生します。このため、アプリケーションは kill シグナル Ctrl-C を含むシグナルに応答できません。
  • Python 3.6 以降を使用します。

次のステップ

Stackdriver Profiler インターフェースの使用で Profiler のグラフとコントロールについて学習します。詳細については、以下をご覧ください。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。