話題のランタイムBunのパフォーマンスを体験してみた

導入

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の動向を注視していきたいです。

無料相談実施中
AWSを使用したサーバーレスアプリケーションの構築
サーバーレス開発内製化、AWSへの移行等
様々な課題について無料でご相談お受けいたします。
最新情報をチェックしよう!