AWS Lambdaのパフォーマンス改善(1)

2024.03.26
マルチクラウド 技術 セキュリティ AWS クラウド活用 パフォーマンス改善
AWS Lambdaのパフォーマンス改善(1)

はじめに

こんにちは。技術本部 アーキテクチャ&テクノロジー部の髙橋 洋樹です。AWS Lambdaをテーマに投稿している本ブログシリーズ。前回はAWS Lambdaがどのような仕組みで動いているのかを中心に説明しました。まだお読みでない方は、ぜひこちらからご覧ください。
さて、今回と次回では、実際にAWS Lambdaのパフォーマンスをどのように改善していくのかについて、具体的に解説していきます。

必要なのは推測ではなく、計測

では早速、パフォーマンス改善の話に入っていきましょう。パフォーマンス改善を効果的に実施していくには、施策を実施した後の効果測定が重要なため、「パフォーマンスを計測できる状態にしておくこと」が必須です。ある施策を実施したとしても、それが計測できなければ効果がわからないためです。例えば、AWS Lambda関数、特にランタイムとしてJavaとC#を利用しているが、なんだか処理が遅いとなった場合、まず計測したいのはINITフェーズとINVOKEフェーズの所要時間です。どちらの所要時間を改善したいのかで、対応内容が異なってきます。

両フェーズの所要時間を計測するためにはAWS X-Rayを利用できます。AWS X-Rayはアプリケーションが処理するリクエストに関するデータを収集するサービスです。リクエストやレスポンスにかかる時間やステータスなどのデータを収集し、コンソールで表示・分析することで問題の特定につなげることができます。AWS X-Rayのコストが不安で利用を尻込みしてしまう方がいるかもしれませんが、AWS X-Rayはトレース数に対する従量課金で毎月の無料利用枠があり※1、枠内で利用する分には料金は一切かからないので安心してください。

さて、AWS X-Rayの利用開始方法ですが、マネジメントコンソール対象のLambda関数の設定画面から[設定>モニタリング及び運用ツール>編集]と遷移し、AWS X-Ray アクティブトレースを有効化すればOKです。

画面:Lambda関数のAWS X-Ray利用開始手順

画面:Lambda関数のAWS X-Ray利用開始手順

アクティブトレースを有効化した状態で、Lambda関数がリクエストを受け付けてしばらくするとサービスマップが表示されます。

画面:AWS X-Rayのサービスマップ

画面:AWS X-Rayのサービスマップ

画面にはサービスマップと合わせてタイムラインも表示されており、Initialization、Invocation、Overheadいう項目とそれぞれの所要時間が確認できます。このInitializationがINITフェーズの所要時間、InvocationフェーズがINVOKEフェーズの所要時間を表しています。

画面:AWS X-Rayのタイムライン

画面:AWS X-Rayのタイムライン

もしInitializationの項目がない場合はウォームスタートしているということなので、Initializationの項目があるそれ以前のトレースを参照してください。

INITフェーズのパフォーマンスを改善

INITフェーズに想定より時間がかかっている場合には、そもそもINITフェーズが発生しないようにする、もしくは、INITフェーズの処理時間を短縮するという2パターンの改善策があります。それぞれ具体的に解説していきます。

1. INITフェーズが発生しないようにする方法

Provisioned Concurrencyを設定する

Provisioned ConcurrencyはINITフェーズが完了した状態のLambda関数を事前に指定した環境数だけ常に立ち上げておくAWS Lambdaの機能です。環境数を上回る数のリクエストが一度に来なければコールドスタートは発生しません。AWS Application Auto Scalingにも対応しているので、実際に利用されている実行環境の数に合わせて環境数を増減させることも可能です。なお当然ながら環境を常に立ち上げておくぶん別途料金が発生するので、その点には留意する必要があります。

Lambda SnapStartを利用する(Javaのみ)

Lambda関数のランタイムとしてJava 11以降を採用している場合に限られますが、Lambda SnapStartというAWS Lambdaの機能を利用することができます。これはINITフェーズが完了した直後の実行環境のメモリとディスクの状態を取得しておき、ウォームスタート時にAWS Lambda関数が必要とする部分のみロードすることで高速化を図る機能です。Provisioned Concurrencyと比較して追加料金なしで利用できるのが嬉しい点です。なお、Lambda SnapStartとProvisioned Concurrencyの併用はできません。

ちなみに、JVMの遅延ロードの仕様上、ライブラリはアプリケーションではじめて使用されるまで読み込まれません。この状態でLambda SnapStartを設定したとしてもINITの時間はたいして変化しません。ハンドラー外でダミーのAPIコールを行うなどしてINITフェーズで読み込まれるようにしましょう。

ポーリングを行う

EventBridgeルールなどを使用してAWS Lambda関数を定期的に呼び出し、SHUTDOWNフェーズに移行しないようにする方法です。この方法はよく知られていますが、コールドスタートの発生を確実に防止できるわけではないので注意が必要です。防止できない理由はいくつかありますが、理由の一つとしてLambdaの実行環境が複数必要だった場合、ウォームな環境をポーリングのターゲットに直接指定することができない、というのが挙げられます。

2. INITフェーズの処理時間を短縮する方法

ライブラリを必要なものに限定する

コードが読み込むライブラリを必要なものに限定することで、INITフェーズの高速化が期待できます。例えば以下のようにライブラリ全体を読み込むのではなく、一部の必要なもののみ読み込むようにします。

画面:必要なライブラリのインポート

画面:必要なライブラリのインポート

メモリを増強する

AWS Lambda関数のスペックは指定されたメモリの量によって決定されます。CPUのスペックは指定することができませんが、割り当てられたメモリに比例してスペックが決定します。そのため、高いメモリを割り当てれば、それだけINITフェーズで実施される処理の高速化が期待できます。一方で当然ながら、高いメモリを指定するとそれだけ時間単価が高くなる点は留意する必要があります。

おわりに

さて、今回はAWS Lambdaのパフォーマンス改善にあたり、効果測定に役立つサービスのご紹介と、INITフェーズのパフォーマンス改善方法についてご紹介しました。紹介したパーマンス改善方法のパターンを表にまとめると下記のようになります。

横にスクロールできます

改善方法 手法 デメリット&制限
INITフェーズが
発生しないようにする
Provisioned Concurrencyを設定 コストが増える
Lambda SnapStartを利用 Javaのみ対応
ポーリングの実施 確実に発生を防止できるわけではない
INITフェーズの
処理時間を短縮する
ライブラリを必要なものに限定
メモリを増強 コストが増える場合がある

次回は、INVOKEフェーズの改善方法について引き続き説明していきますので、実践的なノウハウを知りたい方は、ぜひ楽しみにしていてください。また、当社では、AWSサービスの表面的な技術ノウハウに留まらず、サービスの裏側の仕組みまでを踏まえた上で、アプリケーションやアーキテクチャの改善提案をしております。AWS包括的技術支援サービスを提供しておりますので、AWS Lambdaのパフォーマンス改善に限らず、何かお困りごとがあればお気軽にお問い合わせください!

関連ページ

おすすめブログ

AWS Lambdaのパフォーマンス改善(2)
AWS Lambdaのパフォーマンス改善(2)
今回は、AWS LambdaのライフサイクルでINITフェーズの次にくるINVOKEフェーズのパフォーマンス改善方法を中心に説明していきます。