Lambda 関数の Java ランタイムの起動時の動作をカスタマイズする
このページでは、AWS Lambda の Java 関数固有の設定について説明します。これらの設定を使用して、Java ランタイムの起動時の動作をカスタマイズできます。これにより、コードを変更することなく、関数全体のレイテンシを低下させ、関数全体のパフォーマンスを向上させることができます。
JAVA_TOOL_OPTIONS 環境変数について
Java を使用する場合、Lambda は追加のコマンドライン変数を設定するために、JAVA_TOOL_OPTIONS 環境変数をサポートします。この環境変数は、階層化コンパイル設定のカスタマイズなど、さまざまな方法で使用できます。次の例では、このユースケースで JAVA_TOOL_OPTIONS 環境変数を使用する方法を示します。
例: 階層型コンパイル設定のカスタマイズ
階層型コンパイルとは、Java 仮想マシン (JVM) の機能です。JVM のジャストインタイム (JIT) コンパイラを十分に活用するため、特定の階層型コンパイル設定を使用することができます。通常、C1 コンパイラは起動時間を短縮するように最適化されています。C2 コンパイラは、全体的なパフォーマンスを最大限に高めるように最適化されていますが、メモリの使用量が多く、処理に時間がかかります。階層型コンパイルには 5 つの異なるレベルがあります。レベル 0 では、JVM は Java バイトコードを解釈します。レベル 4 では、JVM は C2 コンパイラを使用して、アプリケーションの起動時に収集されたプロファイリングデータを分析します。時間の経過とともに、コードの使用状況を監視して最善の最適化方法を特定します。
階層型コンパイルのレベルをカスタマイズすると、Java 関数のパフォーマンスを調整するのに役立ちます。短時間で実行される小さな関数の場合、階層型コンパイルをレベル 1 に設定すると、JVM が C1 コンパイラを使用することによってコールドスタートの性能を向上させることができます。この設定は、最適化されたネイティブコードを迅速に生成しますが、プロファイリングデータは生成せず、C2 コンパイラも使用しません。大規模で計算負荷の高い関数の場合、階層型コンパイルをレベル 4 に設定することで、全体的なパフォーマンスを最大化できますが、その分メモリ使用量が増加し、各 Lambda 実行環境がプロビジョニングされた後の最初の呼び出し中に追加の最適化処理が発生します。
Java 11 およびそれ以前のランタイムの場合、Lambda はデフォルトの JVM 階層型コンパイル設定を使用します。Java 17 および Java 21 の場合、Lambda はデフォルトでレベル 1 で階層型コンパイルを停止するように JVM を設定します。Java 25 以降においても、Lambda はデフォルトで階層型コンパイルをレベル 1 で停止します。ただし、SnapStart またはプロビジョニングされた同時実行を使用する場合は、デフォルトの JVM 設定が使用されます。これらのケースでは階層型コンパイルが呼び出しパスの外部で実行されるため、コールドスタートのペナルティを発生させることなく、SnapStart とプロビジョニングされた同時実行のパフォーマンスを向上させます。この利点を最大化するには、プリミングを使用できます。これは、関数の初期化時にコードパスを実行して、SnapStart スナップショットを取得する前、または Provisioned Concurrency の実行環境が事前プロビジョニングされているときに JIT をトリガーできます。詳細については、ブログ記事「Optimizing cold start performance of AWS Lambda using advanced priming strategies with SnapStart
階層型コンパイル設定をカスタマイズするには (コンソール)
-
Lambda コンソールの [関数]
ページを開きます。 -
階層型コンパイルをカスタマイズする Java 関数を選択します。
-
[設定] タブを選択し、左側のメニューで [環境変数] を選択します。
-
[編集] を選択します。
-
[環境変数の追加] を選択します。
-
[キー] に、
JAVA_TOOL_OPTIONSと入力します。[値] に、-XX:+TieredCompilation -XX:TieredStopAtLevel=1と入力します。
-
[保存] を選択します。
注記
Lambda SnapStart を使用して、コールドスタートの問題を軽減することもできます。SnapStartは、実行環境のキャッシュされたスナップショットを使用して、起動時のパフォーマンスを大幅に向上させます。SnapStartの機能、制限事項、サポートされているリージョンの詳細については、Lambda SnapStart による起動パフォーマンスの向上 を参照してください。
例: JAVA_TOOL_OPTIONS を使用した GC の動作のカスタマイズ
Java 11 ランタイムは、ガベージコレクションにシリアルJAVA_TOOL_OPTIONS 環境変数を使用してデフォルトの GC を変更することもできます。パラレル GC と Shenandoah GC
例えば、ワークロードでより多くのメモリと複数の CPU を使用する場合は、パフォーマンス向上のためにパラレル GC の使用を検討してください。そのためには、JAVA_TOOL_OPTIONS 環境変数の値に以下の値を追加します。
-XX:+UseParallelGC
ワークロードに存続期間の短いオブジェクトが多数ある場合は、Java 25 で導入された Shenandoah ガベージコレクターの世代モードを有効にすることで、メモリ消費量を抑えられる可能性があります。このためには、JAVA_TOOL_OPTIONS 環境変数の値に以下の値を追加します。
-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
Log4Shell の Log4j パッチ
Java 8、11、17、21 の Lambda ランタイムには、一般的な Java ログ記録フレームワークである Log4j の Log4Shell 脆弱性 (CVE-2021-44228) を軽減するためのパッチが含まれています。このパッチでは、コールドスタートの性能オーバーヘッドが発生します。パッチ適用されたバージョンの Log4j (バージョン 2.17.0 以降) を使用している場合は、このパッチを無効にすることでコールドスタートの性能を向上させることができます。このパッチを無効にするには、環境変数 AWS_LAMBDA_DISABLE_CVE_2021_44228_PROTECTION を true に設定します。
Java 25 以降、Lambda ランタイムには Log4Shell パッチが含まれなくなりました。Log4j バージョン 2.17.0 以降を使用していることを確認する必要があります。
Ahead-of-Time (AOT) キャッシュと CDS キャッシュ
Java 25 以降、Lambda ランタイムには、Java ランタイムインターフェイスクライアント (RIC) の Ahead-of-Time (AOT) キャッシュが含まれています。RIC は、Lambda Runtime API からのイベントをアクティブにポーリングするランタイムコンポーネントです。これにより、コールドスタートの性能を向上させることができます。
AOT キャッシュは JVM ビルドに固有です。Lambda がマネージドランタイムを更新すると、RIC の AOT キャッシュも更新されます。ただし、ユーザーが独自の AOT キャッシュをデプロイすると、それらが無効になったり、ランタイムの更新後に予期しない動作が発生する可能性があります。したがって、マネージドランタイムを使用する場合は AOT キャッシュを使用しないことを強くお勧めします。AOT キャッシュを使用するには、コンテナイメージを使用して関数をデプロイする必要があります。
AOT キャッシュは、Class Data Sharing (CDS) キャッシュでは使用できません。Lambda 関数に CDS キャッシュをデプロイすると、Lambda は AOT キャッシュを無効にします。