導入
BunがNode.jsを代替するのではと話題になっていたため、実際に触ってみようと思いました。
普段はAWS Lambda(Boto3)を使用して開発を行っているため、LambdaをNode.jsとBunで動かした際のパフォーマンスの違いを検証することにしました。
事前の情報収集
検証にあたり参考にさせていただいた記事は以下の2つです。
・Lambda上でBunのカスタムランタイムを動作する方法
https://dev.classmethod.jp/articles/bun-lambda-custom-runtime/
・似た検証を行った方のspeakerdeck
https://speakerdeck.com/smt7174/bun-gameziyaririsusaretakedo-ben-dang-nibun-hanode-dot-js-niqu-tutedai-warunoka-woaws-lambda-dejian-zheng-sitemita?slide=17
他の方の検証だと、意外にもNode.jsの方が速度が出るという結果になっていました。
Bunのインストール
公式のドキュメントの通りに進めます。
https://bun.sh/docs/installation
$ curl -fsSL https://bun.sh/install | bash -s "bun-v1.0.7"
最新版 (v1.0.14)のBunだと後述のLambdaレイヤーの作成時にエラーが起きるため、1.07を指定しています。
Lambdaレイヤーを準備する
公式のレイヤーを使用します。
https://github.com/oven-sh/bun/tree/main/packages/bun-lambda
READMEの通りに進めていきます。
AWS CLIのprofileが正しいか事前に確認しておきましょう。
$ git clone git@github.com:oven-sh/bun.git
$ cd bun/packages/bun-lambda
$ bun install
$ bun run publish-layer
Lambda及びAPIGatewayの設定
今回のパフォーマンステストではPokeAPIからポケモンの名前を取得する処理を計測することにしました。
BunはfetchAPI、Node.jsはaxiosをそれぞれ使用しています。
Bun
const bunCustomRuntime_default = {
async fetch(request) {
const url = new URL(request.url);
const number = url.pathname.split("/").pop();
try {
const pokeApiResponse = await fetch(`https://pokeapi.co/api/v2/pokemon/${number}`);
if (!pokeApiResponse.ok) {
throw new Error(`API responded with status: ${pokeApiResponse.status}`);
}
const pokemonData = await pokeApiResponse.json();
return new Response(pokemonData.name, {
status: 200,
headers: {
"Content-Type": "text/plain"
}
});
} catch (error) {
console.error(error);
return new Response(`Error: ${error.message}`, {
status: 500,
headers: {
"Content-Type": "text/plain"
}
});
}
}
};
export {
bunCustomRuntime_default as default
};
Node.js
const axios = require("axios");
exports.handler = async (event) => {
const number = event.pathParameters.number;
try {
const response = await axios.get(
`https://pokeapi.co/api/v2/pokemon/${number}`
);
const pokemonData = response.data;
return {
statusCode: 200,
headers: {
"Content-Type": "text/plain",
},
body: pokemonData.name,
};
} catch (error) {
return {
statusCode: 500,
headers: {
"Content-Type": "text/plain",
},
body: `Error: ${error.message}`,
};
}
};
それぞれのコードをLambdaにアップロードします。
Bunの方は先ほど準備したレイヤーを設定し、ランタイム設定のハンドラをhandler.fetchに設定します。
最後にそれぞれのLambda関数をAPI Gatewayに統合します。
図鑑番号9でGETして、blastoise(カメックス)が無事返ってきました。
パフォーマンス測定
Postmanを使用します。
それぞれのAPIリクエストを含むCollectionを作成して、Run Collectionからパフォーマンスの測定を実施します。
設定は以下の通り行いました。
結果は以下の通りで、Bunの方がパフォーマンスが優れているという結果となりました。
まとめ
事前に調べた記事だとNode.jsの方が優れている結果だったので、このような結果が出たのが意外でした。
結果が異なる原因は不明ですが、bunのポテンシャルを実感できました。
引き続きbunの動向を注視していきたいです。