はじめに
こんにちは、ほうき星 @H0ukiStar です。
AWS Lambda は、割り当てるメモリのサイズを増やすことによって CPU をはじめとする実行リソースも比例して割り当てられる特徴があります。
そのため、割り当てるメモリサイズを変更することにより処理時間も変化し、処理内容によっては、メモリサイズを増やした方が実行時間を大きく短縮でき、結果として実行コストを下げられる場合があります。
しかし、処理の内容によって当然適切な割り当てメモリサイズは異なり、128MB~10,240MBの中から適切なメモリサイズを手動で確認していくのは、現実的ではありません。
この最適なメモリサイズを見つけるためのツールの1つに、AWS Lambda Power Tuning があります。
本記事では、AWS Lambda Power Tuning を用いて副作用のある Lambda 関数をチューニングする方法を紹介します。
AWS Lambda Power Tuning とは
AWS Lambda Power Tuning は、Lambda 関数のメモリサイズを最適化するためのオープンソースツールです。
はじめにで述べた通り、Lambda 関数は 128MB ~ 10,240MB の範囲でメモリを割り当てることができ、割り当てたメモリサイズに応じて CPU をはじめとする実行リソースも比例して割り当てられます。
また、Lambda 関数は「割り当てメモリ量 × 実行時間」に応じて課金されるため、例えばメモリを 2 倍にしても実行時間が半分以下になれば、実行コストを抑えられる場合があります。
しかし、複数のメモリサイズで Lambda 関数を繰り返し実行し、実行時間やコストを比較する作業を手動で行うのは、現実的ではありません。
AWS Lambda Power Tuning は、このような比較を自動化し、複数のメモリサイズで Lambda 関数を実行して、コストやパフォーマンスを比較・可視化してくれるツールです。
実測値をもとに最適なメモリサイズを判断できるため、経験や勘に頼らないチューニングが可能になります。
本ツールは Alex Casalboni 氏によって公開されており、ソースコードは以下の GitHub リポジトリで公開されています。
デプロイ方法
GitHub リポジトリをクローンして SAM でデプロイする方法や、Serverless Application Repository (SAR) からデプロイする方法などがあります。
本記事では、手軽に利用できる SAR を使用します。
-
AWS Lambda Power Tuning の SAR レポジトリを開き
Deployを押下 -
マネジメントコンソールに遷移しアプリケーションの設定にてパラメータを確認・指定し
IAMロールを作成することを了承しデプロイを押下 -
デプロイタブでステータスが
Create completeであれば完了
Lambda 関数のチューニング方法
AWS Lambda Power Tuning は Step Functions のステートマシンとして実装されています。
このステートマシンにチューニング対象の Lambda 関数 ARN などを渡してチューニングを行います。
-
powerTuningStateMachine を開き
実行を開始を押下 -
入力に以下の json を渡し
実行を開始入力例{ "lambdaARN": "<チューニングしたい Lambda 関数 ARN>", "powerValues": [128, 256, 512, 1024], "num": 10, "payload": {} }-
powerValuesは試行するメモリ割り当てサイズ -
numはメモリ割り当てサイズごとの試行回数 -
payloadはチューニング対象の Lambda 関数へ渡す辞書
-
チューニング結果の確認
ステートマシンの実行完了後実行の入力と出力タブの出力: visualization に記載された URL より、今回試したメモリ割り当て設定に関するレポートをグラフィカルに確認することができます。
例では 512MB の設定が、コスト最適であることが分かりました。
副作用のある Lambda では何が問題になるのか
AWS Lambda Power Tuning は、チューニング対象の Lambda 関数を以下のような流れで実行します。
- 同一のメモリ割り当て設定では
num回分、直列で実行(デフォルトの場合) - 各メモリ割り当て設定間は並列で実行
そのため、チューニング対象の Lambda 関数がデータベースからデータを取得したり書き込んだりする等の副作用を持つ場合、各実行毎に処理条件をそろえるためデータベースへのデータの準備や削除などを別途行う必要があります。
また、処理内容によっては単にデータを準備するだけではなく、各試行が互いに影響しないよう試行ごとに独立したデータセットを用意する必要があります。
例えば、データの更新や削除を伴う処理では、同じレコードを複数の試行で共有すると実行結果が前回の試行に影響され、正しい性能比較ができなくなる可能性があります。
このような課題を解決する方法として、AWS Lambda Power Tuning には各試行の前後で任意の Lambda 関数を実行できる preProcessorARN と postProcessorARN が用意されています。
preProcessorARN / postProcessorARN を利用したデータベースへのデータの準備・削除
AWS Lambda Power Tuning のステートマシンは preProcessorARN と postProcessorARN で前処理・後処理を行う Lambda 関数を指定することができます。
このプロパティを使用することで、チューニング対象の Lambda 関数がデータベース等への副作用を伴う場合であっても、各実行毎にデータの準備や削除を行うことができます。
{
"lambdaARN": "<チューニングしたい Lambda 関数の ARN>",
"powerValues": [128, 256, 512, 1024],
"num": 10,
"payload": {},
"preProcessorARN": "<前処理を行う Lambda 関数の ARN>",
"postProcessorARN": "<後処理を行う Lambda 関数の ARN>"
}
preProcessorARN および postProcessorARN を指定した場合、AWS Lambda Power Tuning は各試行ごとに以下のような流れで処理を実行します。
ただしこの場合、以下の疑似コードで示されるように、ステートマシン実行時に指定した payload は前処理を行う Lambda 関数に渡され、前処理を行う Lambda 関数の出力がチューニング対象の Lambda 関数に渡されます。
function Executor:
iterate from 0 to num:
[payload = execute Pre-processor (payload)]
results = execute Main Function (payload)
[execute Post-processor (results)]
そのため、チューニング対象の Lambda 関数に payload を渡したい場合は、前処理を行う Lambda 関数で受け取った payload を出力するように実装する必要がある点に注意してください。
この挙動は preProcessorARN を利用した場合のみ発生します。前処理を利用しない場合は、指定した payload がそのままチューニング対象の Lambda 関数へ渡されます。
さいごに
AWS Lambda Power Tuning は、Lambda 関数のメモリサイズを最適化するうえで非常に便利なツールですが、「副作用を伴う Lambda には適用しづらい」と感じていた方もいるのではないでしょうか。
本記事で紹介したように、preProcessorARN と postProcessorARN を利用することで、各試行の前後でデータの準備・後片付けを行うことができ、データベースなどの状態を変更する Lambda 関数に対しても、同一条件でチューニングを実施できます。
また、payload の受け渡し方法など、実際に利用してみて気付きやすいポイントもあるため、これから利用する方はぜひ押さえておくことをおすすめします。
Lambda 関数の性能やコストを最適化する際の選択肢として、本記事が参考になれば幸いです。







