Closed6

なんでbun installは速いのか?

laisolaiso

A global install cache.

bun installを実行すると ~/.bun/install/cache/ 以下にnpmレジストリからダウンロードされたファイルの実体が展開されキャッシュされる(--cache-dirでパスを変更できる)。

キャッシュにはパッケージのバージョンごとのディレクトリとlatestのシンボリックリンクがある。これらのファイルを使ってbun install時に該当するバージョンのダウンロードを省く(--forceで再ダウンロードする)。

このため一度bun installしてlockfileが作成されると次はオフラインでinstallを実行しても成功する。

node_modules/を削除しても~/.bun/install/cache/からファイルを取ってくるのでネットワークアクセスをしない。

laisolaiso

Optimized file writes.

node_modules/ 以下にファイルを配置する時に the fastest system calls を使うとある。

例えばmacOSではclonefileat()を呼び出すためにOSごとに分岐していた。

  1. https://github.com/oven-sh/bun/blob/80e1f32ca1236dcf6f7ed559c596afbced0f8f3a/src/install/install.zig#L1481
  2. https://github.com/oven-sh/bun/blob/80e1f32ca1236dcf6f7ed559c596afbced0f8f3a/src/install/install.zig#L1110

https://qiita.com/hnw/items/ba721a34790d50686563

同じくキャッシュからnode_modules/ を生成するpnpmはシンプルにシンボリックリンクを張って回っているので実装に違いがあるらしい。

bun installで生成されたnode_module以下のファイルをstatコマンドで見てみたところリンクファイルじゃなくて実体だった。

laisolaiso

A binary lockfile.

速さとは直接関係なさそうだけど、bunのlockfileはバイナリで吐き出される。

これはbun-lockfile-format-v0という形式で、bunコマンドで実行するとyarnv1形式のプレーンテキストを吐いてくれる。

❯ bun bun.lockb | head
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
# bun ./bun.lockb --hash: 5D27A8E737B929B1-08d055213fe5158d-223CA8C1A1ADEB6B-1c1460a293fede0f


"@aashutoshrathi/word-wrap@^1.2.3":
  version "1.2.6"
  resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz"
  integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==

https://bun.sh/guides/install/yarnlock

bun installに限らずbunはデコードするとJavaScriptになる中間形式を各所で吐き出して高速化しているので、インストール時にも何か関係があるのかもしれない。

laisolaiso

pnpmとの比較の話

Evan Youがベンチマークを同条件にして比較している。それによると

  • キャッシュの有無でのパッケージダウンロードが発生するか
  • lockfileを生成するためのNPM APIのアクセス

が重要らしい。

https://twitter.com/youyuxi/status/1701243745880932687

https://twitter.com/youyuxi/status/1701243750666703338

筆者環境でもbunとpnpmでキャッシュとlockfileを用意して比較すると差は5-6倍程度だった。これなら妥当な感じ。

とすると後はダウンローダーとパッケージ展開のプログラムの処理スピードで差が出ているなと予想した。

laisolaiso

Zig実装が速い

インストールコマンドの実装は src/install/ あたりにある。

https://github.com/oven-sh/bun/tree/b651b16fdd959b349c09ec5d5056229dcd12c86b/src/install

HTTPClientもmulti-threaded処理も含んだzig実装なので単にシングルスレッドなNode.jsスクリプトで実行するよりは速くなりそうだというbun devでNext.jsが実行される仕組みを調べるで調べた時と同じ感想になった。

https://github.com/oven-sh/bun/blob/main/src/install/install.zig

もう少し解像度の高い解説はZigつよつよな人にお願いしたい。

このスクラップは2023/09/20にクローズされました