AWS Lambdaの実行速度をX-Rayで計測する

2022.01.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

AWS Lambdaのコールドスタート・ウォームスタートにかかった時間を
計測する必要があったので、測定方法について
社内で聞いたところ、下記のような意見をいただきました。

  • CW Logsに出力されるLambdaのログ見ればCW LogsInsightsとかで分析できる
  • 単純な時間の計測だけならX-Rayが手軽
  • Lambda→Lambda呼び出しで計測できる
  • 視覚的にボトルネックを把握したいとかであればX-Rayが便利
  • 何度も計測して結果を集計したいなら自前で計算が必要なので、CloudWatch Lambda Insightsが楽

今回は簡単にいきたいため、X-Rayを使って計測しました。  

AWS X-Ray?

AWS X-Rayはアプリケーションの分析やデバッグ用サービスです。
アプリに対するリクエストされたデータを収集&分析して詳細な情報を確認できます。
もちろん、AWS Lambdaに対しても適用可能になってます。  

対象のLambda関数でアクティブトレースを有効化して適切なロールを付与すると、
実行時にデータをX-Rayに送信し、X-Rayはデータを処理して分析情報を生成します。

X-Rayはサービスによって処理されるリクエストに関する情報を記録します。
Lambdaの場合、後述するInitialization、Invocation、Overhead
のサブセグメントの情報が記録されます。  

Initialization

Lambda実行環境ライフサイクルの初期フェーズ。
コールドスタートにかかる時間がこれになります。
設定したリソースを使用して実行環境を作成(もしくはフリーズ解除)し、
関数とすべてのレイヤーをダウンロード後にランタイムの初期化と関数の初期化を実施します。

Invocation

Lambdaが関数ハンドラを呼び出すフェーズ。
ランタイムと拡張機能の登録、ランタイムがレスポンスを送信する準備ができたら終了です。

Overhead

ランタイムが応答を送信してから、次の呼び出しのシグナルを送信するまでに発生するフェーズ。

Environment

以下の環境で試しました。 aws cliは実行可能な前提です。

  • OS : MacOS 11.3.1
  • Node: 16.2

Measure Speed (Javascript)

Lambda作成

では適当なLambda関数を定義し、X-Rayで測定してみましょう。
AWSコンソールのLambda画面で、Nodeランタイムの関数を作成します。

関数の内容はなんでもよいです。
今回は↓のような内容のLambdaをAWSコンソール上で記述しました。  

exports.handler =  async (event, context) => {
  const response = {
      statusCode: 200,
      body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
}

X-ray設定

設定 > モニタリングおよび運用ツール > 編集
と進み、AWS X-RayのアクティブトレースをOnにして保存しましょう。
これでLambda実行結果をX-Rayで確認できます。

Lambda実行

登録したLambdaを実行します。
AWSコンソールのテストタブからでもいいし、
aws cliのlambda invokeでもかまいません。

X-Rayみてみる

コンソールでX-rayへいき、計測結果を確認してましょう。
初回であればInitializationの項目があり、コールドスタートしているのがわかります。

Appendix

ツール使ってやってみる

1回だけならさきほどのような手動実行でいいのですが、
回数が増えると手間です。
今回調査するにあたって雑にLambda実行とX-ray計測のスクリプトを作りました。
※ リージョン/実行方法/結果取得時間 とかはかなり適当

このnodeプログラムを↓のように実行して、

% node run-lambda.js run <Lambda関数名> <実行回数>

↓でX-Ray結果を取得しました。

% node parse-xray.js

いくつかの言語で計測した

Node(Javascript)以外にも、Deno、Rust、Go、JavaでLambdaを定義して計測してみました。

言語 ランタイム メモリ コードサイズ リージョン
Python Python 3.9 128M 299.0 byte us-west-2
Go Go 1.x 128M 4.2 MB us-west-2
Javascript Node 14.x 128M 251.0 byte us-west-2
Rust Custom runtime on Amazon Linux 2 128M 2.3 MB |us-west-2
Deno(TypeScript) Custom runtime on Amazon Linux 2 128M 8.4 MB us-west-2
Java Java 11 (Corretto) 128M 342.0 byte us-west-2

結果は↓です。Javaのコールドスタートがぶっちぎりで遅い。

*Lambda関数を各100回実行した平均

References