2022年7月初旬、サーバサイドJavaScriptの世界に突然現れたJavaScriptランタイム「Bun」 - Node.jsやDenoを大きく上回るといわれる高速性や、Zigで書かれたエンジンなどが話題となっていますが、実際のところ、本当に既存のJSランタイムを凌駕する存在なのか、そしてBunの登場をきっかけにJSランタイムの世界はどう変わっていくのか - 登場時からBunを見てきたTechFeed JavaScriptエキスパートの古川陽介氏に、TechFeedの白石俊平がオンラインでお話をうかがいました。本稿ではインタビュー前編として、Bunの設計思想と高速性にフォーカスした内容をお届けします。
今回話を伺ったエキスパート
フォローしよう!
Bunの原点は「打倒 Node.js」
白石: あらためてなんですけど、まず「Bun」とは何なのか、そこから教えていただけるでしょうか。
古川: いわゆる”JavaScriptのランタイム”と呼ばれているものなんですが、ランタイムという説明だけだとちょっとわかりにくいですよね。少し回りくどい言い方をすると、JavaScriptってそもそも言語ではあるんですが、JavaScriptの言語仕様の中にはたとえばファイルを扱うとか、HTTPのサーバとして振る舞うとか、いわゆるサーバサイドの言語、たとえばRubyとかPerlとかPythonなどには普通にある機能そのものが、ごっそり抜けているんですよ。なので、その周辺を固めてサーバサイドでも使えるようにしたり、実行できる環境を作った、それがJavaScriptのランタイム環境です。JavaScriptのランタイムの定義はここでは、要はサーバサイドで動くJavaScriptと認識してもらえばそんなに間違いではないです。
白石: なるほど。同じJavaScriptのランタイムというと、すでにNode.jsとかDenoとかがあるわけですが、それらと比較するとBunはどういったところが特徴的なのでしょうか。
古川: これはものすごくBunの人々がめちゃくちゃ気にしているところだと思うんですが、Bunの思想というかフィロソフィーというか哲学としては「打倒 Node.js」なんですよ。
白石: ええ!?
古川: Bunのサイトの最初のページには「あなたのローカルコンピュータやサーバ、エッジで動いているJavaScriptやTypescriptが実行しているものを全部Bunに置き換えること、これがBunが最初にめざすことです(Bun is designed as a drop-in replacement for your current JavaScript & TypeScript apps or scripts — on your local computer, server or on the edge. )」って書いてあるんです。なのでNode.jsやDeno、これらはBunからすれば打倒すべき競合相手ですね。
ただ、DenoもNode.jsを打倒するために生まれてきたわけなんです。両者にはすごく戦略の違いがあって、ここがおもしろいところなんですけど、DenoはNode.jsの世界観とは決別して新しい世界、つまりDenoという別の世界を作ろうとしています。一方、BunはNode.jsの世界そのものを飲み込みたい、これが(Denoとの)大きな違いです。
なのでBunのほうがNode.jsのAPIをそのまま採用していたり、Web APIと呼ばれているFetchのようなクラウドネイティブなAPIを率先して対応していたりするのは、いろいろな環境で動いているNode.js、最近だとエッジ、CDNの環境で動いているCloudflare Workers上のJavaScript環境なんかもすべてこっち(Bun)に寄せてくれと思っているんだと思います。なのでマーケティング上の戦略がDenoとははっきり違います。
Denoは「新しい世界を目指す」、Bunは「Node.jsをまるごと飲み込む」 - これが対Node.js戦略の違い
Node.jsとの互換性は「それほどでも…」
白石: なるほど、おもしろいですね。この世界観のお話や今後の展開に関してはあとでまたお聞きするとして、Bunそのものについての詳細を伺えれば。まず、Node.jsとの互換性については実際のところどうなんでしょうか。
古川: Bunの中ではけっこう互換性に配慮していて、「90%以上のAPIが動きます」とか書いてあるんですが、実際僕が触った2、3週間前、Bunが出てきたばかりのころ(2022年7月初旬)なんですけど、そのころはまだまだでしたね。
たとえばNode.jsのAPIでHTTPサーバを作るところなんかはちゃんと動かなくて、BunのHTTPサーバのままだったし。あとはファイルシステム、ファイルを読んだり書いたりする部分も動くとはいわれていたんですが…いちおう動くは動くんですが、コンピュータが読み込んだものをちゃんと人間が読めるようには、いったんエンコードされてしまっているものをデコードする必要があるんですが、そのデコードするところがまだ甘いんです。ためしに、読み込んだものがそのままファイルとして表示できるかなと思って、普通にファイルとして書き出したものをファイルとして読み込んで表示する…とやってみたんですが、ちゃんと動かなかったんですよね。Node.jsだと実際にちゃんと動くコードを(Bunで)動かしたら、いちおう振る舞いとしては動いているんですけど、中で返ってくる表示結果は(Node.jsと)全然違っていて、正直、まだまだだなと。
白石: それは文字コードの問題なんでしょうか?
古川: そうです。JavaScriptの文字列は内部的にはバイナリデータとして格納されています。Node.jsはそのバイナリデータを人間の目にも見えるようにデコードする仕組みとしていくつか用意されていますが、 ファイルから読み込んだデータをデコードするのにBufferというAPIがその役割を担っています。ただ BunはBufferのいくつかのAPIがうまく動かず、 APIを呼び出してもデコードしてくれずにバイナリデータをそのままでしまっていました。「デコードしてくれないのかー」と思いましたね。
ただそれももしかしたら、何週間かしたら採用してくるのかもしれないですね。今のところBunのバージョンはまだv0.1.4(※7/22時点)くらいなので、そのレベルだとまだデコードまで手が回ってないだけかなという気がします。ただ、今の時点では本当に(Node.jsと)互換しているかというと、互換ではないですね。
BunのNode.js互換性は「まだ甘い」
Bunがウリにしている高速性、本当にNode.jsより3倍速いのか!?
白石: 次のポイントとして、Bunは「速い」ということがだいぶ宣伝されているかなと思うんですが、なんで速いんでしょうか? 「本当に速いのか」と「なんで速いのか」についてぜひ。
古川: これですね、すごくマーケティングがうまいと思う。わりといろいろな人から「なんでこんなに速いの?」って聞かれるんですが、よく見てみると、ベンチマークスペックの内容はたしかに3倍くらい速さに差があったりするんですが、本当によーく見るとベンチマークしているときの内容って、Reactのサーバサイドレンダリングとか「Hello World」みたいな、すごくシンプルで本当にリアルワールドではない、たとえばすごくシンプルなHTMLをただ表示するだけで「(Node.jsやDenoより)3倍速い」と言っているというか。たしかに「3倍速い」という結果は出ているのかもしれないですが、それはリアルワールドの結果ではない。もっと本当は複雑なんですよ、リアルワールドのサーバサイドレンダリングは。いろいろなコンポーネントを入れたり、LOOPで回したり…実際そこまでやって、本当に「3倍速い」という結果が出るのかというのは不透明だと思っています。なので「速さの理由」については今のところ、若干、懐疑的な目で見たほうがいいと思います。
ま、いわゆるマイクロベンチってやつですね。本当の意味でのリアルワールドでのベンチマークではなく、マイクロベンチマークの結果で速かったというのはたしかにそうだと思います。
もう少し補足すると、マイクロベンチマークの結果が速かった理由もちゃんとある。おそらくですけど、Zigというプログラミング言語部分に理由があると思っています。とくにReactのサーバサイドレンダリングした結果をちゃんと追うと、実は中でReactのストリームで返しているんですね。Node.jsのストリームを使って返すということをやってるんですけど、Node.jsはストリームの実装がJavaScriptで書かれています。おそらくですけどDenoもJavaScriptもしくはTypeScriptで書かれているんじゃないかと思います。一方でBunはZigでストリームの処理を書いています。この部分に差があるのでは…というのが僕がいろいろな人たちと話して得た印象です。
まとめると、そもそも(Bunが)速いかどうかというと、そこにはまず懐疑的です。マイクロベンチの速い理由はおそらくZigにあるんじゃないかと思います。なので「めちゃくちゃ爆速!」と宣伝していますけど、そこも含めてOSSのマーケティング戦略としてはおもしろいですね。
Bunのベンチマーク結果については懐疑的、マイクロベンチが速い理由はZigにあるのではと推測、これらも含めてマーケティング戦略がうまい!
→ ひきつづき、Bunの技術選択、JSランタイムの今後の展望などについて古川氏が解説したインタビュー後編もあわせてお読みください。