本記事は、2022年11月に開催された
Japan Node.
JSConf JPを2022年11月26日に開催予定で、今回のテーマであるNode.
今日はBunについてお話しします。過去にNode学園でお話しした内容とほとんど同じですが、聞いたことがある方はおさらいとして聞いていただければと思います。
Bunとは
Bunは新しいJavaScriptのランタイムで、Node.
ちなみに2022年1月ごろには私もBunのことをキャッチしていて、社内でもZigで書かれていることなどに注目していました。当時のBunのWebサイトのOGタグには
その後、2022年8月ごろにBun v0.
ちなみにBunという名前は、BundleのBunと、それらを包み込むという意味から中華まん
Bunが目指すところは、主に3つあります。
- 高速に起動すること
- 次世代のパフォーマンス
- ツールとしてgreat and completeであること (Bundler / Transpiler / Package managerを内包すること)
また、BunのWebサイトの最初にはこう書かれています。
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. Bun natively implements hundreds of Node.
js and Web APIs, including ~90% of Node-API functions (native modules), fs, path, Buffer and more. The goal of Bun is to run most of the world's JavaScript outside of browsers, bringing performance and complexity enhancements to your future infrastructure, as well as developer productivity through better, simpler tooling.
- Bunは既存のJavaScript / TypeScriptアプリケーションやスクリプト
(ローカルコンピュータで動いているもの、サーバで動いているもの、Edgeで動いているものすべて) のランタイムを完全に置き換えられるように設計されている - 数百のNode.
js API / Web APIをネイティブで実装することを目指している (Node. jsのAPIと互換性があり、ローカルコンピュータやサーバで動いているNode. jsを置き換えることができ、Edgeでも動かせる) - Bunのゴールは、ブラウザ外で動くJavaScriptのランタイムとしてのシェアNo.
1である。さらにパフォーマンスや複雑さの改善を将来のインフラストラクチャに取り込み、より良いシンプルなツールセットにより開発生産性を実現する
このように、Bunは手元のPCであろうとEdgeであろうと、既存のJavaScript / TypeScriptランタイムをすべて置き換えることを目標とした、とても意欲的なプロジェクトです。そのためにWeb APIとNode.
現在Bunがサポートしている機能
Web APIのうち、Fetch / WebSocket / ReadableStreamなどはすでにBunに実装済みです。
node_
BunではTypeScript/Bun.
というAPIも用意されているので、BunのJSXやTypeScriptトランスパイラを呼び出してカスタマイズすることもできます。
Bunにはsqliteが最初から同梱されていて、import sqlite from ”bun:sqlite”
で使えます。Edgeではsqliteを使うことも多いので、そのために同梱されているのかもしれません。.env
ファイルで環境変数をロードする処理も最初から対応しており、DX
驚いたのはNode-APIbun:ffi
このあたりのネイティブモジュールへの対応は、昔PHPでFacebookがHHVM
Bunのパフォーマンス
BunのWebサイトにはv0.
このベンチマークで何をしているのかを見てみると、少なくともv0.
こちらはBunのトップページに掲載されているrenderToReadableStream
の部分でパフォーマンスに差が出ている可能性があります。
Bunのページで紹介されているベンチマーク結果を見ると、他のランタイムに比べて3倍以上の開きがあり、Bunが非常に高速に見えますが、実際はマイクロベンチマーク的な内容であり、特定の関数をピックアップした結果と考えたほうがいいでしょう。ただ、BunではrenderToStreamもZigで実装しているので、この特定の関数についてはJavaScriptで実装している他のランタイムと比較して速いというのは正しいと思います。
Bunが速い理由 - Node.jsとの比較
Bunのサイトでは、V8ではなくJSCを採用したこと
Bunのパフォーマンスを理解するために、Node.
Node.
同じようにBunの内部構造を表現すると、このようになります。
- Node.
jsではV8だったところが、BunではJavaScriptCoreになっている - http-parser → pico-http-parser、libuv → kqueue/
iouring - http/
2, quick層は未実装 (v0. 1時点)
Standard Library - APIの互換性
Node.
Node.
HTTP Parserの違い - http-parser vs pico-http-parser
Node.
http-parserとpico-http-parserは趣きが違います。http-parserはヘッダをパースした時点でNode.
JavaScriptエンジンの違い - V8 vs JSCの最適化
最近のJavaScriptエンジンは単なるインタプリタではなく、Just In Timeコンパイラにより統計的に状況をみて高速化されます
クルマに例えるとギア
V8は3段変速ギアと表現できます。
- Ignition
(1速) … 単にbytecodeを生成する - Sparkplug
(2速) … bytecodeから変数解決/脱糖衣構文化などを実施する - Turbofan
(3速) … 統計情報をもとに型レベルでの最適化を実施する
一方でJSCは4段変速ギアと表現できます。
- LLInt
(1速) … 単にbytecodeを生成する - Baseline JIT
(2速 … bytecodeから簡単なJIT生成コードを作る - DFG JIT
(3速) … データフローに基づく最適化を実施し、主に戻り値の型チェックなどを行って最適化する - FTL JIT
(4速) … SSAによる最適化 (型レベルでの最適化) を実施する (V8のTurbofanと同様)
IO抽象化レイヤの違い - libuv vs kqueue/iouring
Node.
まとめ - JavaScriptランタイムは”戦国時代”に突入!?
ここまで見てきたように、BunはNode.
ただ、Bunがプロダクションレディであるかというと、まだまだという印象です。とはいえBunは現在v0.
個人的にはJavaScriptランタイムはNode、Deno、Bun、Cloudflare Workersなどを交えて今戦国時代が始まったと感じています。三国志にたとえると、魏=Node.
一方でJavaScriptランタイムの互換性については、WINTER CGと呼ばれるWeb互換のJavaScriptランタイム仕様を決めようとする動きも出ているため、この流れは追っていきたいところです
以上で発表を終了します。ありがとうございました。