Python アプリケーションのプロファイリング
このページでは、プロファイリング データを収集し、そのデータを Google Cloudプロジェクトに送信するように Python アプリケーションを変更する方法について説明します。プロファイリングの全般的な情報については、プロファイリングのコンセプトをご覧ください。
Python のプロファイル タイプ:
- CPU 時間
- 経過時間(メインスレッド)
サポートされている Python 言語バージョン:
- Python 3.6 ~ 3.11.0。
サポートされているプロファイリング エージェントのバージョン:
- エージェントの最新リリースがサポートされています。一般に、1 年を超える期間が経過したリリースはサポートされません。エージェントの最新リリース バージョンを使用することをおすすめします。
サポートされているオペレーティング システム:
- Linux。Python アプリケーションのプロファイリングは、標準 C ライブラリが glibcまたはmuslで実装されている Linux カーネルでサポートされています。Linux Alpine カーネルに固有の構成情報については、Linux Alpine で実行するをご覧ください。
サポートされる環境:
- Compute Engine
- Google Kubernetes Engine(GKE)
- App Engine フレキシブル環境
- App Engine スタンダード環境(Python 3 ランタイム環境が必要)
- Google Cloud の外部(追加の構成要件については、 Google Cloudの外部で実行されているアプリケーションのプロファイリングをご覧ください)。
Profiler API を有効にする
プロファイリング エージェントを使用する前に、基盤となる Profiler API が有効になっている必要があります。Google Cloud CLI または Google Cloud コンソールのいずれかを使用して、API のステータスを確認し、必要に応じて有効にできます。
gcloud CLI
- ワークステーションに Google Cloud CLI がまだインストールされていない場合は、Google Cloud CLI のドキュメントをご覧ください。 
- 次のコマンドを実行します。 - gcloud services enable cloudprofiler.googleapis.com
詳細については、gcloud services をご覧ください。
Google Cloud コンソール
- 
  
   
   
     
   
  
 
  
  
    
      Enable the required API. Roles required to enable APIs To enable APIs, you need the Service Usage Admin IAM role ( roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.
- [API が有効です] が表示されている場合、API はすでに有効になっています。そうでない場合は、[有効にする] ボタンをクリックします。 
サービス アカウントに IAM ロールを付与する
Google Cloud リソースにアプリケーションをデプロイしていて、デフォルトのサービス アカウントを使用しており、そのサービス アカウントに対するロール付与を変更していない場合は、このセクションをスキップできます。
次のいずれかを行う場合は、サービス アカウントに Cloud Profiler エージェント(roles/cloudprofiler.agent)の IAM ロールを付与する必要があります。
- デフォルトのサービス アカウントを使用しているが、ロール付与を変更している。
- ユーザーが作成したサービス アカウントを使用している。
- ワークロード ID を使用している場合は、Cloud Profiler エージェントのロールを Kubernetes サービス アカウントに付与します。
サービス アカウントに IAM ロールを付与するには、Google Cloud コンソールまたは Google Cloud CLI を使用します。たとえば、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
前述のコマンドを使用する前に、次のように置き換えます。
- GCP_PROJECT_ID: プロジェクト ID。
- MY_SVC_ACCT_ID: サービス アカウントの名前。
詳細については、プロジェクト、フォルダ、組織へのアクセスを管理するをご覧ください。
Cloud Profiler の使用
Python の使用に関するおすすめの方法については、Python 開発環境の設定をご覧ください。
Compute Engine
Compute Engine の場合は、次の操作を行います。
- C/C++ コンパイラとデベロッパー ツールをインストールします。 - sudo apt-get install -y build-essential
- pip をインストールします。 - sudo apt-get install -y python3-pip
- Profiler パッケージをインストールします。 - pip3 install google-cloud-profiler
- 初期化コードのできるだけ早い段階で - googlecloudprofilerモジュールをインポートし、- googlecloudprofiler.start関数を呼び出します。- start関数に- serviceパラメータを指定する必要があります。Profiler インターフェースでアプリケーションのバージョンをフィルタするには、- service_versionパラメータを指定します。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。
GKE
GKE の場合は、次の操作を行います。
- Dockerfile を変更して Profiler パッケージをインストールします。 - FROM python:3 ... RUN apt-get update && apt-get install -y build-essential python3-pip RUN pip3 install google-cloud-profiler
- 初期化コードのできるだけ早い段階で - googlecloudprofilerモジュールをインポートし、- googlecloudprofiler.start関数を呼び出します。- start関数に- serviceパラメータを指定する必要があります。Profiler インターフェースでアプリケーションのバージョンをフィルタするには、- service_versionパラメータを指定します。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。
フレキシブル環境
App Engine フレキシブル環境の場合は、次の操作を行います。
- requirements.txtファイルに- google-cloud-profilerを追加します。
- 初期化コードのできるだけ早い段階で - googlecloudprofilerモジュールをインポートし、- googlecloudprofiler.start関数を呼び出します。
App Engine の場合、service と service_version はオペレーティング環境から取得されます。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。
スタンダード環境
App Engine スタンダード環境の場合は、Python 3 ランタイム環境を使用する必要があります。次の操作を行います。
- requirements.txtファイルに- google-cloud-profilerを追加します。
- 初期化コードのできるだけ早い段階で - googlecloudprofilerモジュールをインポートし、- googlecloudprofiler.start関数を呼び出します。
App Engine の場合、service と service_version はオペレーティング環境から取得されます。トラブルシューティングと例外の詳細については、トラブルシューティングをご覧ください。
start 関数
googlecloudprofiler.start 関数は、プロファイルを継続的に収集してアップロードするデーモン スレッドを作成します。アプリケーションのできるだけ早い段階で start を 1 回呼び出す必要があります。
| パラメータ | 説明 | 
|---|---|
| service1 | (必須)プロファイリングされるサービスの名前。サービス名の制限については、サービス名とバージョンの引数をご覧ください。 | 
| service_version1 | (省略可)プロファイリングされるサービスのバージョン。サービスのバージョンに関する制限については、サービス名とバージョンの引数をご覧ください。 | 
| verbose | (省略可)ロギングレベル。ロギングレベルの詳細については、エージェント ロギングをご覧ください。 デフォルト値は 0(エラー)です。 | 
| project_id2 | (省略可) Google Cloud プロジェクト ID。 | 
| disable_cpu_profiling | (省略可)CPU プロファイリングを無効にするには、 disable_cpu_profiling=Trueを設定します。このパラメータは、Python バージョン 3.2 ~ 3.11.0 でサポートされています。他のバージョンの Python の場合、CPU プロファイリングはサポートされていないため、このパラメータは無視されます。 デフォルト値は False です。 | 
| disable_wall_profiling | (省略可)経過時間プロファイリングを無効にするには、 disable_wall_profiling=Trueを設定します。このパラメータは、Python バージョン 3.6 ~ 3.11.0 でサポートされています。他のバージョンの Python の場合、経過時間プロファイリングはサポートされていないため、このパラメータは無視されます。 経過時間プロファイリングが有効な場合の start関数の制限については、制限事項をご覧ください。デフォルト値は False です。 | 
1 Compute Engine と GKE のみ。App Engine の場合、値は環境から取得されます。
  2 Google Cloudの場合、値は環境から取得されます。Google Cloud 以外の環境では、値を指定する必要があります。詳細については、 Google Cloudの外部で実行されているアプリケーションのプロファイリングをご覧ください。
データの分析
Profiler が収集したデータを Profiler のインターフェースに表示し、分析できます。
Google Cloud コンソールで、[Profiler] ページに移動します。
このページは、検索バーを使用して見つけることもできます。
サービス名とバージョンの引数
Profiler エージェントを読み込むときに、service-name 引数とオプションの service-version 引数を指定して構成します。
Profiler は、サービス名で指定されたサービスのすべてのレプリカからプロファイリング データを収集します。Profiler サービスは、サービス バージョンとゾーンの組み合わせに対して、1 つのサービス名について平均で 1 分あたり 1 個のプロファイルを作成します。
たとえば、1 つのサービスの 2 つのバージョンが 3 つのゾーンのレプリカで実行されている場合、Profiler はそのサービスについて 1 分あたり平均で 6 個のプロファイルを作成します。
レプリカで異なるサービス名を使用している場合、サービスが必要以上にプロファイリングされるため、オーバーヘッドが大きくなります。
サービス名を選択する場合は、次の点に注意してください。
- アプリケーション アーキテクチャでサービスを明確に識別できる名前を選択してください。1 つのサービスまたはアプリケーションしか実行していない場合、どのようなサービス名を選択するかはさほど問題になりません。しかし、アプリケーションが一連のマイクロサービスとして実行されている場合は、名前の選択が重要になります。 
- service-name 文字列で、プロセス ID などのプロセス固有の値を使用しないでください。 
- service-name 文字列は次の正規表現と一致する必要があります。 - ^[a-z0-9]([-a-z0-9_.]{0,253}[a-z0-9])?$
サービス名として imageproc-service のような静的な文字列を使用することをおすすめします。
サービス バージョンは省略可能です。サービス バージョンを指定すると、複数のインスタンスからプロファイリング情報が集約され、バージョンごとに表示されます。これは、複数のバージョンがデプロイされているときの識別に役立ちます。Profiler UI では、データをサービス バージョンでフィルタできます。これにより、コードの新旧バージョンのパフォーマンスを比較できます。
service-version 引数には、自由形式の文字列を指定できますが、通常は、バージョン番号のような値を使用します(例: 1.0.0、2.1.2)。
エージェント ロギング
デフォルトでは、プロファイリング エージェントは重大度が error のメッセージをログに記録します。より低い重大度のメッセージをログに記録するようにエージェントを構成するには、エージェントの起動時に verbose パラメータを指定します。verbose に指定できる値は次の 4 つです。
- 0: エラー
- 1: 警告
- 2: 情報
- 3: デバッグ
start の呼び出しで verbose パラメータを 1 に設定すると、重大度が Warning または Error のメッセージがログに記録され、Informational と Debug メッセージは無視されます。
すべてのメッセージをログに記録するには、エージェントの起動時に verbose を 3 に設定します。
googlecloudprofiler.start(service='service_name', verbose=3)
トラブルシューティング
このセクションでは、Python アプリケーションのプロファイリングに固有の制限事項、例外、既知の問題について説明します。一般的な問題のヘルプについては、トラブルシューティングをご覧ください。
制限事項
| プロファイルの種類 | 制限事項 | 
|---|---|
| 経過時間 | 
 | 
例外
| エラー | 原因 | 解決策 | 
|---|---|---|
| startでNotImplementedErrorがスローされる | アプリケーションが Linux 以外の環境で実行されています。 | 
 | 
| startでValueErrorがスローされる | start関数の引数が無効です。環境変数と引数から必要な情報が特定できません。CPU プロファイリングと経過時間プロファイリングの両方が無効になっているときに、プロファイリングが実行されました。 | 
 | 
既知の問題
| 動作 | 原因 | 解決策 | 
|---|---|---|
| プロファイル データがまったく存在しない、または新しいプロファイル タイプを有効にしているものの、プロファイル データが欠落しています。 | 一般的な原因は構成に関連しています。 | トラブルシューティングをご覧ください。 | 
| uWSGI を使用しているものの、一部のプロセスの CPU 時間と経過時間プロファイルのデータが存在しません。 | uWSGI が複数のワーカーを使用してリクエストを処理する場合、デフォルトの動作では、プライマリ(「マスター」)プロセスでのみアプリケーションの初期化が行われます。フォークしたプロセスでは、初期化シーケンスは行われません。 アプリケーションの初期化シーケンス(Django アプリケーションの  | すべてのワーカー プロセスでアプリケーションの初期化を行うには、lazy-apps フラグを  関連する問題については、この表の次のトピックをご覧ください。 | 
| uWSGIを使用していて、経過時間のプロファイル データはありませんが、CPU 時間のプロファイル データはあります。 | 経過時間プロファイラは Python シグナル モジュールに依存します。Python インタープリタのコンパイルでスレッド サポートを有効にすると、デフォルトの構成では、フォークしたプロセスのカスタム シグナル処理が無効になります。 | uWSGI アプリケーションの場合は、py-call-osafterfork フラグを  関連する問題については、この表の前のトピックをご覧ください。 | 
| Profiler を有効にすると、エラーログに次の新しいエントリが追加されます。 
BlockingIOError: [Errno 11] Resource temporarily unavailable
Exception ignored when trying to write to the signal wakeup fd
        GitHub の問題 | シグナル wakeup ファイル記述子( Cloud Profiler がプロファイルを収集する際には、高い頻度でシグナルがトリガーされます。この動作により、ファイル記述子のバッファの空き容量がなくなる場合があります。 | シグナルが失われても、アプリケーションを安全に実行できる場合は、Cloud Profiler を使用できます。Python 3.7 以降を使用している場合、警告メッセージを無効にするには、 シグナルが失われ、アプリケーションを安全に実行できない場合は、Cloud Profiler の使用を停止することをおすすめします。使用し続けると、シグナル番号がなくなり、エラーログのエントリが過剰になる可能性があります | 
Linux Alpine で実行する
Linux Alpine 用の Python プロファイリング エージェントは、Google Kubernetes Engine の構成でのみサポートされています。
Python プロファイリング エージェントをビルドするには、パッケージ build-base をインストールする必要があります。最終的な Alpine イメージに追加の依存関係をインストールせずに Alpine で Python プロファイリング エージェントを使用するには、2 ステージのビルドを使用し、最初のステージで Python プロファイリング エージェントをコンパイルします。たとえば、次の Docker イメージではマルチステージ ビルドを使用して、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
認証エラー
Linux Alpine で Docker イメージ(golang:alpine や alpine など)を使用すると、次の認証エラーが表示されることがあります。
connection error: desc = "transport: authentication handshake failed: x509: failed to load system roots and no roots provided"
エラーの詳細を確認するには、エージェント ロギングを有効にする必要があります。
上記のエラーは、Linux Alpine の Docker イメージに、デフォルトでインストールされているはずのルート SSL 証明書がないことを示しています。これらの証明書は、プロファイリング エージェントが Profiler API と通信するために必要になります。このエラーを解決するには、次の apk コマンドを Dockerfile に追加します。
FROM alpine
...
RUN apk add --no-cache ca-certificates
その後、アプリケーションを再度ビルドし、デプロイする必要があります。