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

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

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

  • CPU 時間
  • ヒープ(アルファ版。Java 11 と App Engine スタンダード環境が必要です)
  • 経過時間(App Engine スタンダード環境では使用できません)

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

  • OpenJDK および Oracle JDK for Java 7、8、9 または 11。

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

  • 標準 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 はすでに有効になっています。そうでない場合は、[有効にする] ボタンをクリックします。

Profiler エージェントをインストールする

Compute Engine

  1. Profiler エージェント用のインストール ディレクトリを作成します(たとえば /opt/cprof)。

     sudo mkdir -p /opt/cprof

  2. storage.googleapis.com リポジトリからエージェント アーカイブをダウンロードし、インストール ディレクトリに展開します。

    wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
    | sudo tar xzv -C /opt/cprof

GKE

Dockerfile を変更して Profiler エージェントのインストール ディレクトリを作成し、エージェント アーカイブをダウンロードしてインストール ディレクトリに展開します。

RUN mkdir -p /opt/cprof && \
  wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
  | tar xzv -C /opt/cprof

フレキシブル環境

Google Java 8 ランタイムのベースイメージまたは Java 9 / Jetty 9 ランタイムのベースイメージを使用する場合、Profiler エージェントはプリインストールされています。エージェントのインストールに必要な追加の手順はありません。

これ以外のベースイメージの場合は、エージェントをインストールする必要があります。たとえば、次の Dockerfile には、openjdk:11-slim イメージを使用して Profiler エージェントをインストールする手順が含まれ、アプリケーションの起動時に使用されるデフォルトのパラメータが定義されています。

FROM openjdk:11-slim

COPY . .
RUN  apt-get update \
     && apt-get install wget \
     && rm -rf /var/lib/apt/lists/*

RUN mkdir -p /opt/cprof && \
    wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
    | tar xzv -C /opt/cprof

CMD ["java", "-agentpath:/opt/cprof/profiler_java_agent.so=[OPTION1],[OPTION2]", "-jar", "PATH/TO/YOUR/JARFILE"]

この Dockerfile を App Engine フレキシブル環境で使用するには、次の操作を行います。

  • [OPTION1][OPTION2] をアプリケーションに必要なエージェント構成の値に置き換えます。PATH/TO/YOUR/JARFILE を jar ファイルのパスに置き換えます。
  • Dockerfileapp.yaml ファイルと同じディレクトリに置きます。
  • app.yaml ファイルを変更して、カスタム ランタイムを指定します。

スタンダード環境

Google Java 8 ランタイム環境または Java 11 ランタイム環境(ベータ版)の場合、Profiler エージェントがプリインストールされています。エージェントのインストールに必要な追加の手順はありません。

GCP 以外

  1. Profiler エージェント用のインストール ディレクトリを作成します(たとえば /opt/cprof)。

     sudo mkdir -p /opt/cprof

  2. storage.googleapis.com リポジトリからエージェント アーカイブをダウンロードし、インストール ディレクトリに展開します。

    wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
    | sudo tar xzv -C /opt/cprof

Profiler エージェントを読み込む

アプリケーションをプロファイリングするには、自身のプログラムを実行する場合と同じように Java を起動します。ただし、エージェント構成オプションを指定します。エージェント ライブラリのパスを指定し、ライブラリにオプションを渡します。

App Engine スタンダード環境の場合、エージェントは自動的に読み込まれ、構成されます。プログラムを起動するに進んで、プログラムの構成と起動を行ってください。

エージェントの構成

プロファイリング エージェントを構成するには、アプリケーションの起動時に -agentpath フラグを指定します。

 -agentpath:[INSTALL_DIR]/profiler_java_agent.so=[OPTION1],[OPTION2],[OPTION3]

ここで、[INSTALL_DIR] はプロファイリング エージェントのパス、[OPTION1][OPTION2][OPTION3] はエージェント構成オプションです。たとえば、[OPTION1]-cprof_service=myapp で置き換える場合は、サービス名を myapp に設定します。オプションの数や順序に制限はありません。サポートされている構成オプションは次のとおりです。

エージェント オプション 説明
-cprof_service アプリケーションが App Engine で実行されていない場合、この構成オプションを使用してサービス名を設定する必要があります。サービス名の制限については、サービス名とバージョンの引数をご覧ください。
-cprof_service_version サービスのバージョンごとに Profiler UI を使用してプロファイリング データを分析する機能が必要な場合は、このオプションを使用してバージョンを設定します。バージョンの制限については、サービス名とバージョンの引数をご覧ください。
-cprof_project_id GCP の外部で実行している場合、このオプションを使用して GCP プロジェクト ID を指定します。詳細については、GCP の外部で実行されているアプリケーションのプロファイリングをご覧ください。
-cprof_zone_name アプリケーションが GCP で実行されている場合、プロファイリング エージェントは Compute Engine メタデータ サービスに接続してゾーンを決定します。プロファイリング エージェントがメタデータ サービスに接続できない場合は、このオプションを使用する必要があります。
-cprof_gce_metadata_server_retry_count
-cprof_gce_metadata_server_retry_sleep_sec
この 2 つのオプションにより、プロファイラ エージェントが Compute Engine メタデータ サービスに接続して GCP プロジェクト ID とゾーン情報を収集するときに使用する再試行ポリシーが定義されます。

デフォルトのポリシーでは、1 秒間待機して次の試行を行います。試行は最大で 3 回まで行います。大半の構成は、このポリシーで十分です。
-cprof_cpu_use_per_thread_timers 正確な CPU 時間をプロファイリングするには、このオプションを true に設定します。このオプションを使用すると、スレッドごとのオーバーヘッドが増加します。

デフォルト値は false です。
-cprof_force_debug_non_safepoints デフォルトでは、プロファイリング エージェントは、すべてのセーフポイントのデバッグ情報だけでなく、すべてのジャストイン タイム(JIT)生成コードのデバッグ情報も JVM に生成させます。これにより、CPU 時間プロファイルとヒープ プロファイルで関数または行レベルの最も正確なロケーション情報を取得できますが、エージェントで追加のオーバーヘッドが発生します。このオプションを false に設定すると、JIT コードのデバッグ情報の生成を無効にできます。

デフォルト値は true です。
-cprof_wall_num_threads_cutoff デフォルトでは、アプリケーションのスレッドの合計数が 4,096 を超える場合、経過時間プロファイルは収集されません。この上限により、プロファイルの収集中に、スレッドのスタックを走査するコストを最小限に抑えることができます。サービスに通常 4,096 を超えるスレッドがあり、追加のオーバーヘッドが発生してもプロファイリング データを収集する場合は、このフラグを使用して上限を引き上げます。

デフォルトの上限は 4,096 スレッドです。
-cprof_enable_heap_sampling Java 11 以降でヒープ プロファイリングを有効にするには、
-cprof_enable_heap_sampling を true に設定します。Java 10 以前ではヒープ プロファイリングを使用できません。

ヒープ プロファイリングはデフォルトで無効になっています。

ヒープ プロファイリングを有効にすると、サンプリング間隔はデフォルトで 512 KiB に設定されます。ほとんどのアプリケーションは、この間隔で十分です。アプリケーションのオーバーヘッドは 0.5% 未満です。256 KiB(262144)から 1,024 KiB(1048576)までのサンプリング間隔がサポートされています。たとえば、サンプリング間隔を 256 KiB に設定してサンプリング レートを 2 倍にするには、次のようにエージェント オプションを追加します。

-cprof_heap_sampling_interval=262144
同様に、サンプリング間隔を 1,024 KiB に設定して、サンプリング レートを半分にするには、次のようにエージェント オプションを追加します。

-cprof_heap_sampling_interval=1048576

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

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)。

プログラムを起動する

Compute Engine

自身のプログラムを実行する場合と同じように Java を起動し、エージェント構成オプションを追加します。

java \
    -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myservice,-cprof_service_version=1.0.0 \
    [JAVA OPTIONS] -jar PATH/TO/YOUR/JARFILE [PROGRAM OPTIONS]

GKE

サービス コンテナの Dockerfile を変更して、自身のプログラムを実行する場合と同じように Java を起動し、エージェント構成オプションを追加します。

CMD ["java", \
    "-agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myservice,-cprof_service_version=1.0.0", \
    "-javaopt1=val1", "-javaopt2=val2", "-jar", "PATH/TO/YOUR/JARFILE", \
    "-programopt1=val1", "-programopt2=val2"]

フレキシブル環境

app.yaml 構成ファイルを修正して、PROFILER_ENABLE 環境変数を設定します。いつもどおりプログラムを起動します。

env_variables:
   PROFILER_ENABLE: true

詳しくは、環境変数の定義をご覧ください。

スタンダード環境

app.yaml または appengine-web.xml 構成ファイルを変更して、GAE_PROFILER_MODE 環境変数を追加します。これにより、同じデプロイのすべてのインスタンスについて、平均で 1 分間に 1 回、CPU プロファイルとヒープ プロファイルを収集するように Profiler に指示します。

app.yaml:

env_variables:
   GAE_PROFILER_MODE: cpu,heap

appengine-web.xml:

  <env-variables>
    <env-var name="GAE_PROFILER_MODE" value="cpu,heap" />
  </env-variables>

その後、通常どおりプログラムを起動します。

詳しくは、環境変数の定義をご覧ください。

エージェント ロギング

プロファイリング エージェントは、App Engine フレキシブル環境、Compute Engine、GKE に関するロギング情報を報告できます。サポートされているロギングレベルは次のとおりです。

  • 0: すべてのメッセージをログに記録します。デフォルトのロギングレベルです。
  • 1: 警告メッセージ、エラー メッセージ、致命的問題のメッセージをログに記録します。
  • 2: エラー メッセージと致命的問題のメッセージをログに記録します。
  • 3: 致命的問題のメッセージだけをログに記録してアプリケーションを停止します。

デフォルトのロギングレベルで標準エラーにログを書き込めるようにするには、-agentpath 構成に -logtostderr を追加します。

エラー メッセージと致命的問題のメッセージだけをログに記録するようロギングレベルを設定するには、-agentpath 構成に -minloglevel=2 を追加します。

たとえば、エラー メッセージと致命的問題のメッセージを標準エラーに記録できるようにするには、-agentpath 構成に -logtostderr‑minloglevel=2 を追加します。

 java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-logtostderr,-minloglevel=2 -jar myApp.jar

次のステップ

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

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

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