Tune Up AWS Lambda
Keisuke Nishitani (@Keisuke69)
Amazon Web Services Japan K.K.
Jan 17, 2017
Profile
Keisuke Nishitani
Specialist Solutions Architect, Amazon Web Service Japan K.K
@Keisuke69 Keisuke69
✤ Specialist SA
- Serverless
- Mobile
- DevOps
- Application Service
✤ RESTおじさん
✤ 餃⼦の王将エヴァンジェリスト(⾃称)
✤ ⾳楽が好きです、フジロッカーです、今年も⾏きます
✤ ブログ: http://keisuke69.hatenablog.jp/
Keisuke69 Keisuke69Keisuke69x
AWS Lambdaにおける
パフォーマンスに関する基本
同時実⾏数
同時実⾏数の考え⽅
✤ イベントソースがAmazon Kinesis / DynamoDBの場合、シャード数と等しくなる
⎻ ストリームのシャードごとに同時に実⾏されるため
⎻ 例:100シャードのAmazon Kinesis ストリームの場合、同時実⾏数はどの時点でも最⼤ 100 件。
そのうちアクティブなシャードが10個だった場合、実際の同時実⾏数は10となる。
✤ それ以外は、(1 秒あたりのイベント数 * 関数の実⾏時間)となる。たとえば、
関数が 1 秒あたりのイベント数が10 件で平均実⾏数が3秒の場合、同時実⾏数は
30となる
1s 2s 3s 4s 5s
10 req/sec
Avg 3s / exec
“同時”に実⾏されているタイミング
同時実⾏数の制限緩和
✤ 制限緩和可能
⎻ デフォルトは100
✤ ただし、実績がない状態でいきなり申請しても通らない可能性が⾼い
⎻ 実際にThrottleされているかどうかの確認を
⎻ Throttleされているかなどはメトリクスで確認可能
Lambdaファンクションの
ライフサイクル
Lambdaファンクションのライフサイクル
✤ Lambdaファンクションはコンテナとして実⾏される(Sandbox)
✤ コンテナのライフサイクルとして開始・終了・再利⽤の3つのサイク
ルがある
Lambdaファンクションのライフサイクル
- 開始 -
✤ ファンクション作成後、もしくはコードや設定更新後の初回実⾏時は新たにコン
テナが作成され、ファンクション⽤のコードがコンテナ内にロード・展開される
⎻ VPC内のリソースにアクセスするように設定したファンクションの場合、ENIがないとその⽣
成オーバーヘッドも追加される
✤ ランタイム側では、ハンドラが最初に呼び出される前に初期化コードが実⾏され
る
✤ これをコールドスタートと⾔う
✤ ファンクションが終了し、ある程度時間が経過したのち再度実⾏される場合は
コールドスタートとなる
Lambdaファンクションのライフサイクル
- 終了 -
✤ 複数の終了パターン
⎻ Timeout
⎻ ユーザが指定した実⾏時間を超えた場合。その時どういう処理が⾏われているかは関係なく、
即時停⽌される
⎻ Controlled termination
⎻ ファンクション内部でアプリケーション的に終了した場合。Node.jsの場合、この時点で他の
コールバックが実⾏されてるかに関わらず終了する
⎻ Default termination
⎻ 全てのコールバックが終了してファンクション⾃体が終了した場合
✤ クラッシュもしくはprocess.exit()を呼び出すことでも終了
⎻ 例えば不具合のあるライブラリが含まれていて、セグメンテーション違反を起こした
場合、そのコンテナは実⾏終了となる
Lambdaファンクションのライフサイクル
- 再利⽤ -
✤ コードの変更がなく前回の実⾏から時間が⽴っていない場合は以前の
コンテナやENIを再利⽤することがある
⎻ ランタイムの初期化処理をスキップできるなどパフォーマンス上のアドバンテ
ージ
⎻ 再利⽤された場合、最後に/tmpに書き込んだ内容も残っているがあてにはしな
いこと
✤ 再利⽤されていることが保証されているわけではない
⎻ リクエスト状況などにより、再利⽤可能なコンテナが埋まっている場合などは
新たなリクエスト処理のためにコールドスタートが発⽣する
Lambdaファンクションのライフサイクル
- プロセスの凍結と再開 -
✤ ファンクションの終了時に実⾏中のバックグラウンドプロセスがある
場合、Lambdaはプロセスをfreezeさせ、次回ファンクションを呼び
出した際に再開する
⎻ ただし、コンテナが再利⽤される場合だけであり保証はされていない
✤ この場合、バックグラウンドプロセスは残っていても処理は⾏われて
いない
⎻ プロセス再作成のオーバーヘッドを減らせる
パフォーマンス関連設定
パフォーマンスに関連する設定
✤ メモリ設定
⎻ 設定値としてはメモリとなっているが実際はコンピューティングリソース全体の設定
⎻ メモリサイズと⽐例してCPU能⼒も割り当てられる
⎻ 最⼩から少しずつ調整し、変更しても性能が変わらない値が最適値
✤ バッチサイズ
⎻ Kinesis/DynamoDBをイベントソースとする際の設定項⽬
⎻ ⼀度に取得する最⼤レコード数(注: 必ずこの数で取得するわけではない)
⎻ なるだけ多く取得してファンクション内でループ等で処理したほうがオーバーヘッド
は少ない
⎻ シャード数⾃体を増やすことで同時処理数も増えるので、どちらが最適かは実ワーク
ロードで調整が必要
Lambdaファンクションを速くする
Lambdaファンクションを速くする⽅法
✤ コールドスタートを速くする
✤ ファンクションの実⾏時間を短くする
✤ 同時実⾏性をあげる
コールドスタートを速くする
コールドスタートを速くする
✤ コールドスタートを減らす
⎻ そもそもコールドスタートを発⽣させない
⎻ 定常的にリクエストが発⽣するシステムではほとんど発⽣しない
⎻ バースト時は別
✤ Lambdaファンクションに対してPingする
⎻ 定期的にInvokeを⾏うことでコンテナが破棄されることを回避する
⎻ 5分間隔程度がオススメ
⎻ API Gatewayを利⽤している場合は該当のAPIへリクエスト
⎻ それ以外は必要な数だけ⾮同期でInvokeする
コールドスタートを速くする
✤ コンピューティングリソースを増やす
⎻ メモリ設定
⎻ コンピューティングリソースの割当を増やすことで初期化処理⾃体も速くなる
✤ ランタイムを変える
⎻ JVMの起動は遅い
⎻ ただし、⼀度温まるとコンパイル⾔語のほうが速い傾向
✤ VPCを使わない
⎻ そもそもLambdaと関係なくENIの⽣成とアタッチ処理は遅い
⎻ コールドスタートを速くしたいならデータストアはDynamoDBが鉄則
⎻ DBの問題でどうしてもVPCを利⽤したい場合はDynamoDB Streamsを利⽤した⾮同期
反映を検討する
コールドスタートを速くする
✤ パッケージサイズを⼩さくする
⎻ サイズが⼤きくなるとコールドスタート時のコードのロードおよびZipの展開に
時間がかかる
⎻ 不要なコードは減らす
⎻ 依存関係を減らす
⎻ 不要なモジュールは含めない
⎻ 特にJavaは肥⼤しがち
⎻ JavaだとProGuardなどのコード最適化ツールを使って減らすという⼿もある
⎻ 他の⾔語でも同様のものはある
コールドスタートを速くする
✤ Javaの場合だけ
⎻ POJOではなくバイトストリームを使う
⎻ 内部で利⽤するJSONシリアライゼーションライブラリは多少時間がかかるので、バイトス
トリームにしてより軽量なJSONライブラリを使ったり最適化することも可能
⎻ https://github.com/FasterXML/jackson-jr
⎻ http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-stream.html
⎻ 匿名クラスをリプレースするようなJava8の機能を利⽤しない(lambda、メソ
ッド参照、コンストラクタ参照など)
ファンクションの実⾏時間を速くする
ファンクションの実⾏時間を速くする
✤ コンピューティングリソースを増やす
⎻ メモリ設定
✤ 各⾔語のベストプラクティスに従う
✤ グローバルスコープを有効に使う
⎻ AWSのクライアントやDBコネクションなど
⎻ ファンクションのコンテナが再利⽤される際、これらも再利⽤される
⎻ 初期化コードをハンドラ外に置く場合はコールドスタートに影響するので注意
グローバルスコープを有効に使う
import boto3
client = None
def my_handler(event, context):
global client
if not client:
client = boto3.client("s3")
# process
同時実⾏性をあげる
同時実⾏性をあげる
✤ 同時実⾏性の⾼いアーキテクチャにして処理全体のスループットを向上させる
✤ 同期でInvokeすると同時実⾏数の制限に引っかかってつまりがちなので⾮同期で
Invokeするのがオススメ
⎻ なお、ほとんどのイベントソースからは⾮同期でトリガーされる
✤ 1ファンクションの実⾏時間は可能な限り短くすること
✤ 例
⎻ S3イベントで⼤きなファイルを処理する場合、親ファンクションで細かく分割して、⼦ファン
クションを⾮同期でInvokeする
⎻ Kinesisの場合、シャード数を増やす
⎻ DynamoDBの場合はシャード数のコントロールは⾃動なので難しい
まとめ:Lambdaのパフォーマンスをあげるには
✤ パフォーマンス関連の基本
⎻ メモリ設定はメモリだけでなくコンピューティング能⼒の設定
⎻ コールドスタートとウォームスタート
⎻ 同時実⾏数
✤ Lambdaファンクションを速くする
⎻ コールドスタートを速くする
⎻ ファンクションそのものの実⾏を速くする
✤ 同時実⾏性をあげることで全体のスループットをあげる
Tune Up AWS Lambda

Tune Up AWS Lambda