nodejsの代わりに llrt ランタイム利用でaws lambda 低コスト関数URL環境を利用する

# llrtランタイムってそもそも何か？

## あらすじ
最近業務で AWS lambda(python or nodejs)ばかりの開発をやっております。

以前より、サーバレス環境を使ったり、自分でサーバレスフレームワークを作ってみたりしてたのですが、一方で欠点である「コールドスタート問題」があるので「社内向けのツール等」で利用してました。

業務の一環として「コールドスタートの高速化」について調べていた所、タイトルにあるような
- llrt(v0.5.1-beta)

これが「lambda nodejs」の代替えとして「AWSが作成オープンソース化」で利用可能と言うのが「色々書かれてた」内容がグーグルで見つかりました。

ただ普通に日本語でググると、大体
- 2024/02頃の記事が目立つ

わけで、じゃあ実際に「どうやって lambda で動かすの？」から、まず「そもそもHouTo」的な感じで記載されたものが存在しなかったので、今回記載したいと思います。

## lambda で使ってみる（セットアップ方法）

### llrt をダウンロードする

まず以下から「zipファイル」をダウンロードします。
https://github.com/awslabs/llrt/releases
-  llrt-lambda-arm64-full-sdk.zip (ARM64のCPUを利用する場合)
-  llrt-lambda-x64-full-sdk.zip (Intel系の64bitCPUを利用する場合)

上のどちらかを「ダウンロード」します。

また上の内容は `full=AWS-SDK-V3環境がフルに入ってる` ので、これの利用が一番適してると思うので、これをダウンロードします。

次にAWSにログインして「コンソールのホーム」から「Lambda」を実行します。

### 先程ダウンロードしたzip をレイヤー登録する
1. lambda
2. レイヤー
3. レイヤーを作成

上のように実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117964/fd2036c0-dd37-4466-a176-26ce4ba98d10.png)
- 名前: llrt
- 説明 - オプション: llrt v0.5.1-beta full
- zipファイルをアップロード -> ファイルを選択
- 互換性のあるアーキテクチャー オプション: arm64 or x86_64
- 互換性のあるランタイム- オプション: Amazon Linux 2023

※ arm64 or x86_64 は、対象zipファイルのCPUに応じて設定を変更してください.
一旦これで登録すると良いかと

### llrt 実行用の 関数を作成する
1. lambda
2. 関数
3. 関数を作成

上のように実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117964/1cc09611-8400-4e7e-9918-ab835844d0c5.png)
- 関数名: 任意で（例: testLLRT)
- ランタイム: Amazon Linux 2023
- アーキテクチャー: x86_64 or arm64(任意)
- それ以外(任意)

確定した場合は「関数を作成」で、関数を作成します。

### 生成関数に先程のレイヤーを追加する

そして、一旦「関数作成」ができましたら、対象の関数を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117964/f205ad45-3000-4b27-8979-a32717b8c8af.png)

ここの「Layers」をクリックして「レイヤー登録」を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117964/086d135d-9776-42e7-8c82-dc3b3c2f290c.png)
- カスタムレイヤーを選択
- カスタムレイヤ: さきほど登録したレイヤーを選択(llrt)
- バージョン: 今回新しく登録なら「１」を選択
- 追加ボタンを押下

これで対象lambdaに対象のレイヤー登録が行えました。

### 対象関数に登録されてるファイル郡は全削除

次にやる事は amazon linux 2023 登録時のデフォルトファイル(shなど)を全て削除します。

そのあと以下のように
- index.js
~~~js
exports.handler = async function (event) {
   return {hello: "world"};
}
~~~

こんな感じのindexファイルを登録して、試しに「テスト」で実行してみると普通に実行成功すると思います。

これで `llrt` が動作する lambda 環境が作成できました（ぱちぱちぱちー）

# 次に気になる関数URL利用においてNodejsとllrtの速度の差やメモリ利用を検証してみた

## 関数URL化して、通常のNodeJs(V22)と速度比較

一旦llrtランタイムで動作する環境が作れたら、現状では普通に関数URLも動作します。

ちなみに関数URLの作成方法は
1. 設定
2. 関数URL

を有効にする事で「関数URL」のURLが発行されます。

今回 llrt で作成した関数URL環境および、nodejs(v22)環境の動作速度比較を行なうため、一旦現在私が作成中の `minto`
- https://github.com/maachang/minto

これを実際に使って「速度比較」を行いたいと思います。

ここで普通に「AWS-SDK-V3」の「S3Client」機能を利用する形で、実際の「コールドスタート比較」を行いたいと思います。

なお、実行対象環境は以下の通りです。

- アーキテクチャー: arm64
- メモリ: 128mb

この環境でnodejs版とllrt版で同じ内容を実施してみた結果が以下となります。

- lambda: node22 memory:128mb
> REPORT RequestId: 828f62d0-ddf7-4f81-81d6-b3bd777bfd72 Duration: 4801.02 ms Billed Duration: 4802 ms Memory Size: 128 MB Max Memory Used: 97 MB Init Duration: 156.66 ms 

- Duration: 4802 ms
- Memory Used: 97 MB

Nodejs実行だと、実行速度は4.8秒、メモリが97MB と速度遅いし、メモリギリギリですね。

- lambda am2023(llrt-v0.5.1-beta full) memory:128m
> REPORT RequestId: 3851698e-8163-4f38-a9f6-3d943a064465 Duration: 190.13 ms Billed Duration: 258 ms Memory Size: 128 MB Max Memory Used: 31 MB Init Duration: 67.85 ms 

- Duration: 190.13 ms
- Memory Used: 31 MB

一方で llrt さすがの速度圧巻ですね。

上の内容は「コールドスタート」時のもので、当然ですが「AWS-SDK3のS3Client=大量のモジュールを読み込み必要がある」ので、128mb環境(cpu0.5)だと、nodejsで驚異の `4.8秒`と言う「超遅い」結果となっています。

一方の「llrt」環境での「同条件」の「コールドスタート」が `258ミリ秒` と「めちゃくちゃ速い」結果となっています。

実に5.3%の実行時間に短縮されてるわけですが、更にびっくりなのが「メモリの利用容量」も「97 MB VS 31 MB」と 約32% のメモリー利用率となっています。

あと別途AWSSDKV3を使わずに「AWS Signature V4」を使って実行した結果も以下に記しておきます。

- lambda: node22 memory:128mb
> REPORT RequestId: 281a1267-2ea3-4a1b-af8a-5ec453880b32 Duration: 2234.31 ms Billed Duration: 2235 ms Memory Size: 128 MB Max Memory Used: 88 MB Init Duration: 134.62 ms 

- lambda am2023(llrt-v0.5.1-beta no-sdk) memory:128m
> REPORT RequestId: 82c60798-6ea5-4f3d-befd-5957174db2c0 Duration: 103.77 ms Billed Duration: 158 ms Memory Size: 128 MB Max Memory Used: 24 MB Init Duration: 53.69 ms

上の llrtはこれまでの AWS-SDK-V3 が入ってないバージョン(llrt-lambda-arm64-no-sdk)があるので、これで実行しています。

結果を見ると(AWS-SDK-V3)
- 190.13 ms
- 31 MB

今回の(AWS Signature V4)
- 103.77 ms
- 24 MB

大体実行速度が半分、メモリ利用が77%で一定の効果はある一方で、別に「AWS-SDK-V3」版を利用しても「何ら問題ない」感じかなあって思います。

こんな感じで「頑張ればlambda 最低メモリの128mb」で「普通に動く関数URLでのWebアプリ」を作る事が「可能」であると言うわけです。

いやあ「非常にすばらしい」わけですが、一方でNodeJSの上で利用できるモジュールや機能の一部が利用できない問題があります。

たとえば「非推奨の __dirname」とか使えなかったりと、具体的には以下
https://github.com/awslabs/llrt/tree/main/llrt_modules

にサポート状況などが記載されています。

ただ一方で
- http, https

などのNodeで利用できる標準モジュールが利用できない等の「互換性」の問題があり当初は「https」使えないと「https.request = httpClient」使えないじゃんって思ってましたが、一方で昨今のNodeJSだと
- fetch

が利用でき、一方で llrt もこれは利用できるので、とりあえず問題はなさそうな感じでした。

それ以外にも「細々と利用できないモジュール等」がありますが、まあ「AWS lambda」の上で利用する場合はとりあえず「問題なさそう」な感じのようですね。

あと llrt は「コードの最適化」等ができないとあるのですが、一方でそもそもの話として「AWS Lambda + 関数URL」って、逆に「最適化とかプーリングとか全く不要」なので、その点からすれば、この「llrt = 関数URL利用で最も有効利用ができる」わけで、いやあ「サーバレスの新たな可能性」を感じました。

以上最後まで呼んでいただき、ありがとうございました。