Slide 1

Slide 1 text

詳解 AWS Lambda コールドスタート 2024.7.29 リテールアプリ共創部 岩⽥ 智哉

Slide 2

Slide 2 text

このセッションで扱うこと 2 コールドスタート関連の⾖知識 ...70%ぐらい 実務に役⽴つ話 ...30%ぐらい

Slide 3

Slide 3 text

⾃⼰紹介 3 岩⽥ 智哉 産業⽀援グループ リテールアプリ共創部 マッハチーム 普段は開発やってます TypeScript and (ECS or Lambda) が多め ⼤阪オフィス所属 好きなAWSサービスはAWS Lambda

Slide 4

Slide 4 text

コールドスタートのライフサイクル 4 AWS Lambda Under the Hood より引⽤ https://serverlessland.s3.amazonaws.com/pdf/mike_danilov_qcon_23_final.pdf

Slide 5

Slide 5 text

コールドスタートを改善するには 5 AWSが最適化する領域について 最適化の恩恵を受けやすくする ユーザー側で最適化すべき領域を 最適化する

Slide 6

Slide 6 text

ここから コールドスタートについて 深堀りしていきます 6

Slide 7

Slide 7 text

Lambdaの実⾏環境について 7 ↓まずはココの話から

Slide 8

Slide 8 text

Lambdaの舞台裏 8 Lambda executions - Security Overview of AWS Lambdaより引⽤ https://docs.aws.amazon.com/whitepapers/latest/security-overview-aws-lambda/lambda-executions.html Worker

Slide 9

Slide 9 text

MicroManager 9 Firecracker: Lightweight Virtualization for Serverless Applications より引⽤ https://assets.amazon.science/96/c6/302e527240a3b1f86c86c3e8fc3d/firecracker-lightweight-virtualization- for-serverless-applications.pdf

Slide 10

Slide 10 text

Full cold StartとPartial cold Start 10 AWS re:Invent 2020: AWS Lambda – Part 2: Optimizing your Lambda function performance より引⽤ https://www.youtube.com/watch?v=rrK7PA8ZK7M

Slide 11

Slide 11 text

LambdaのコードDL 11 ↓続いてココの話

Slide 12

Slide 12 text

コンテナイメージ 形式のLambda 12

Slide 13

Slide 13 text

コンテナイメージ形式のLambda 13 re:invent2020で発表 最⼤10Gのコンテナイメージがデプロイ可能 10Gのイメージが数百msで起動可能

Slide 14

Slide 14 text

なぜコールドスタートが早いのか︖ 14 コンテナイメージを⼩さなチャンクに分割 チャンクは重複排除して保存 オンデマンドでチャンクをロード

Slide 15

Slide 15 text

コンテナイメージの保存⽅法 15 Deep dive into AWS Lambda security: Function isolation より引⽤ https://d1.awsstatic.com/events/reinvent/2020/Deep_dive_into_AWS_Lambda_security_Function_isolation_SVS404.pdf Worker

Slide 16

Slide 16 text

キャッシュヒット率を上げるには 16 AWS が提供するベースイメージは、Lambda サービスによってプロ アクティブにキャッシュされます。つまり、ベースイメージは近く の別のアップストリームキャッシュにあるか、ワーカーインスタン スキャッシュにすでに存在しています。 コンテナイメージとしてパッケージ化された Lambda 関数の最適化 より引⽤ https://aws.amazon.com/jp/blogs/news/optimizing-lambda-functions-packaged-as-container-images/

Slide 17

Slide 17 text

キャッシュの考え⽅は ZIP形式のパッケージにも 共通しているのか︖︖ 17

Slide 18

Slide 18 text

その昔…findmntの実⾏結果 18 TARGET SOURCE …略 ├─/var/task /dev/vdb[/opt/amazon/asc/worker/tasks///] …略 ├─/var/runtime /dev/root[/opt/amazon/asc/worker/runtime/nodejs-8.x] ├─/var/lang /dev/root[/opt/amazon/asc/worker/lang/node-v8.10.x] …略

Slide 19

Slide 19 text

聞いてみた 19 サーバーレスアンチパターン今昔物語 第五夜- 解体新書 - https://www.youtube.com/live/rlYurgnHyFY?si=82MI1poDhq34jGcp ⽬の付け所が良いで すね〜 … これはですね、 回答できません ので、察して下さい

Slide 20

Slide 20 text

LambdaのInit処理 20 最後にココ↓

Slide 21

Slide 21 text

LambdaのInitフェーズ 21 コールドスタート時のみ実⾏されるフェーズ DBとの接続などを管理するためのグローバル変数を宣⾔ するプラクティスが知られている 画像は Comparing the effect of global scope より引⽤ https://docs.aws.amazon.com/ja_jp/lambda/latest/operatorguide/global-scope.html

Slide 22

Slide 22 text

遅延実⾏について 掘り下げて考える 22

Slide 23

Slide 23 text

遅延実⾏ 23 import boto3 client = None def handler(event, context): global client if client is None: client = boto3.client(‘s3’) # ...略 import boto3 client = boto3.client(‘s3') def handler(event, context): # ...略 遅延実⾏なし 遅延実⾏あり

Slide 24

Slide 24 text

遅延実⾏に効果はあるのか︖ 24 Init Invoke Init Invoke t1 t2 Initフェーズの処理をInvokeフェーズに移動することで Initフェーズを⾼速化 Lambda利⽤者から⾒るとコールドスタート時の処理時間 はInitフェーズ + Invokeフェーズ

Slide 25

Slide 25 text

遅延実⾏が効果を発揮するケース 25 def handler(event, context): global client # ...略 if hoge == ‘fuga’ : if client is None: client = boto3.client(‘s3’) Invokeフェーズに移動した処理が呼び出される頻度 次第で全体最適化が図れるかも︖︖

Slide 26

Slide 26 text

遅延実⾏しない⽅が速い︖︖ 26 遅延実⾏あり 遅延実⾏なし

Slide 27

Slide 27 text

boost host CPU 27 InitフェーズではCPU割当が最⼤10秒間までブーストする AWS re:Invent 2019: [REPEAT 1] Best practices for AWS Lambda and Java (SVS403-R1) より引⽤ https://d1.awsstatic.com/events/reinvent/2019/REPEAT_1_Best_practices_for_AWS_Lambda_and_Java_SVS403-R1.pdf

Slide 28

Slide 28 text

遅延実⾏なしの場合 28 import boto3 client = boto3.client(‘s3') def handler(event, context): # ...略 (メモリ割当によらず) ブーストしたCPUパワーで処理

Slide 29

Slide 29 text

遅延実⾏ありの場合 29 import boto3 client = None def handler(event, context): global client if client is None: client = boto3.client(‘s3’) # ...略 メモリ割当に応じたCPUパワーで処理

Slide 30

Slide 30 text

boost host CPUの検証 30 boost host CPU 実行 箇所 メモリ 所要時間 有 INIT 128M 約6.02秒 無 INIT 128M 約84.34秒 無 INV OKE 128M 約85.31秒 無 INV OKE 1769M 約6.08秒 メモリ割り当ての追加は Initフェーズの⾼速化につながらない

Slide 31

Slide 31 text

ここからは⾔語別に コールドスタート改善の TIPSを紹介 31

Slide 32

Slide 32 text

.NET(C#)の場合 32 Native AOT(Ahead-Of-Time) 実⾏時に中間⾔語からコンパイルするのではなく実⾏ 前に事前にコンパイルする⽅式 .NET 8のランタイムからNative AOTに対応

Slide 33

Slide 33 text

Node.jsの場合 33 https://dev.classmethod.jp/articles/node-extra-ca-certs-influence-cold-start/ ~Node.js18x: AmazonのRoot CA証明書を読み込む Node.js20x: 追加のRoot CA証明書は読み込まない /var/runtime/ca-cert.pemに全てのAmazonのRoot CA証明書を含むファイルが配置されている 環境変数NODE_EXTRA_CA_CERTSで指定されたファ イルを追加で読み込む

Slide 34

Slide 34 text

CA証明書読み込みの影響 34 https://dev.classmethod.jp/articles/node-extra-ca-certs-influence-cold-start/ NODE_EXTRA_CA_CERTS min max avg median 95%tile 設定無し 128.56 201.57 139.8471 137.37 168.3 /var/task/ap-northeast-1-bundle.pem 141.45 216.89 155.3957 153.45 170.87 /var/runtime/ca-cert.pem 156.23 220.24 171.9132 171.59 181.15 追加のCA証明書を読み込まない場合は全部⼊りのCA証明書 を読み込む場合と⽐較して平均30ms程度⾼速に

Slide 35

Slide 35 text

不要ファイルはデプロイしない 35 REDME.md *.d.ts 単にnpm installしただけだとnode_modulesの中は 不要ファイルでいっぱい

Slide 36

Slide 36 text

CDKでのNode.js向けレイヤー作成例 36 bundling: { …略 [ …略, 'find node_modules -type l | xargs rm -f’, 'find node_modules -type f -name *.d.ts | xargs rm -f’, 'modclean -r’, 'node-prune’, 'mv node_modules /asset-output/nodejs/', ].join(' && '),

Slide 37

Slide 37 text

レイヤーを使うよりバンドルを 37 ESBuild等でバンドルすることで未使⽤のライブラリはデ プロイパッケージに含めない ライブラリのドキュメントなども⾃動的にデプロイ対象外 になる 最近はJSではなくTSを使うケースが多いので、⾃動的に 恩恵を受けているケースも多いはず

Slide 38

Slide 38 text

今後はLLRTに注⽬ 38 Lambda向けの軽量JavaScriptランタイム JITコンパイラを搭載しない 画像は Lambda Cold Starts analysis より引⽤ https://maxday.github.io/lambda-perf/

Slide 39

Slide 39 text

Javaの場合 39 Java のようなコンパイル済み⾔語の関数でレイヤーを使⽤しても、Python のようなインタープリター⾔語と同じメリットが得られない場合がありま す。Java はコンパイル済み⾔語なので、関数は初期化フェーズで共有アセ ンブリを⼿動でメモリに読み込む必要があり、コールドスタート時間が⻑ くなる可能性があります。代わりに、コンパイル時にすべての共有コード を含めて、組み込みコンパイラ最適化機能を活⽤することをお勧めします。 .zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする より引⽤ https://docs.aws.amazon.com/lambda/latest/dg/java-package.html

Slide 40

Slide 40 text

依存するjarファイルは/libに 40 Java で記述されたデプロイパッケージを Lambda で解凍する所 要時間を短縮します。そのために、依存する .jar ファイルを別個 の /lib ディレクトリにファイルします。これで関数のすべてのコ ードを多数の .class ファイルと⼀緒に単⼀の Jar に収納するより も⾼速化されます。 AWS Lambda 関数を使⽤するためのベストプラクティス より引⽤ https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/best-practices.html

Slide 41

Slide 41 text

パッケージング⽅法の⽐較 41 AWS re:Invent 2020: Ahead of time: Optimize your Java application on AWS Lambda より引⽤ https://d1.awsstatic.com/events/reinvent/2020/Ahead_of_time_Optimize_your_Java_application_on_AWS_Lambda_SVS408.pdf

Slide 42

Slide 42 text

SnapStartを使う 42 re:invent 2022で発表された新機能 Initフェーズ完了後にMicroVMのスナップショットを取得 コールドスタート時にスナップショットからMicroVMをリ ストアして利⽤

Slide 43

Slide 43 text

スナップショットの構成要素 43 メモリ Lambdaのメモリ割り当てに⽐例して⼤きくなる︖ VMの状態 Disk /tmp領域のサイズに⽐例して⼤きくなる︖ ※SnapStartは512MB以上の/tmp領域と併⽤不可

Slide 44

Slide 44 text

SnapStartとメモリの関係 44 AWS Lambda Under the Hood より引⽤ https://serverlessland.s3.amazonaws.com/pdf/mike_danilov_qcon_23_final.pdf

Slide 45

Slide 45 text

リストア時間はメモリに⽐例しない 45 メモリ10GでもRestore Durationは⼗分に短い

Slide 46

Slide 46 text

Pythonの場合 46 du -d 1 -h lib/python3.12/site-packages/botocore/data/ …略 1.6M lib/python3.12/site-packages/botocore/data//ec2 32K lib/python3.12/site-packages/botocore/data//apprunner 28K lib/python3.12/site-packages/botocore/data//lookoutmetrics 28K lib/python3.12/site-packages/botocore/data//redshift-serverless 18M lib/python3.12/site-packages/botocore/data/ コールドスタート⾼速化のためにboto3をスリム化して改善効果を測定してみた https://dev.classmethod.jp/articles/coldstart-with-minified-boto3/ botocoreから不要サービスのJSONを削除すればスリム化が図れる

Slide 47

Slide 47 text

botocoreのjsonを事前解凍 47 endpoint-rule-set-1.json.gz examples-1.json paginators-1.json service-2.json.gz waiters-2.json 必要なAWSサービスの定義を事前に解凍 endpoint-rule-set-1.json examples-1.json paginators-1.json service-2.json waiters-2.json

Slide 48

Slide 48 text

Client⽣成の所要時間を⽐較 48 def handler(event, context): client = boto3.client(‘dynamodb’) client = boto3.client(‘iot’) client = boto3.client(‘iot-data’) client = boto3.client(‘s3’) client = boto3.client(‘sns’) client = boto3.client(‘sqs’) client = boto3.client(‘ssm’) メモリ128MBでコールドスタート時のdurationを⽐較

Slide 49

Slide 49 text

事前解凍で微妙に⾼速化 49 GZIP解凍 件数 最小値 最大値 平均 中央値 95%タイル 無し 99 4317.58 5012.98 4762.81 4772.86 4976.62 有り 99 3254.42 4836.53 4599.8 4610.88 4800.26 filter @type = "REPORT" and ispresent(@initDuration)| stats count(@duration) , min(@duration), max(@duration), avg(@duration), median(@duration) , pct(@duration, 95)

Slide 50

Slide 50 text

⿊魔術的なテクニックの 利⽤にはご注意ください 50

Slide 51

Slide 51 text

最後にまとめ 51

Slide 52

Slide 52 text

まとめ 52 Lambdaを使う以上はコールドスタートは避け られない コールドスタートについて深く理解すること でパフォーマンスが最適化できる このセッションで紹介した知識やTIPSがヒン トになれば

Slide 53

Slide 53 text

良いLambdaライフを︕ 53

Slide 54

Slide 54 text

ありがとうございました 54