bun install は npm より最大90倍速い!?!?──手元でガチ測定してみた
はじめに
・bunってnpmよりinstall速いらしいけど実際どれくらい速いの?
・私の手元でも速いの?
・みんな大好きなあのパッケージでも速いの?
Bunは、JavaScriptランタイムとしてNode.jsの代替を目指しており、パッケージマネージャーとしてだけでなく、以下のような面でも高速化を実現しています:
- 🚀 JavaScriptの実行速度(Node.jsの約4倍)
- 📦 ビルド速度(webpackやesbuildと比較して最大30倍)
- 🔄 Hot Reloading(従来のdev serverより高速)
今回は、その中でも特に開発者の日常的な作業に直結する(?)「パッケージインストール」に焦点を当てて、実際の速度差を検証してみましょう。
ちょうど1年くらい前にWindows対応したBunですが、実際のパッケージインストールはどれくらい速いのでしょうか。
手元でガチ測定してみましょう!
ベンチ用のコードを準備
リポジトリ概要(npm-vs-bun)
ディレクトリ/ファイル | ざっくり中身 | 用途 |
---|---|---|
remix-app/ next-app/ hono-app/ | それぞれ公式スターターを素のまま配置 | 実際の開発でよく使う 3 フレームワークをサンプルに採用 |
bench.sh | mac/Linux 用 Bash スクリプト | hyperfine で npm install / bun install を連続 5 回計測(cold+cached) |
bench.ps1 | Windows (PowerShell) 版 | 同じく 5 回計測。実行ポリシーを変えると動く |
aggregate.py | 標準ライブラリだけの集計スクリプト | 生成された *_cold.json / *_cached.json を読み込み → Markdown テーブル を CLI に出力 |
.gitignore | node_modules/ や JSON, log を除外 | リポジトリを脂肪化させないための保険 |
README.md | OS ごとのセットアップ手順 | 4 つの必須ツール (git / node/npm / bun / hyperfine) があれば動作 |
みなさんのお手元でも実験可能にしておきました。
測定ポリシー("project-cold" とは?)
今回のベンチはwarmupラウンドでグローバルキャッシュにインストール内容を溜めてから node_modules, bun.lockbだけを削除 → 再インストール する
"project-cold" モードで測定しています。
CI の‐every-time クリーンビルド(≒ system-cold)で比べると “ネットの太さ” に結果が支配されがちです。
一方、ローカル開発者が日常的に叩くのは 「node_modules/ を吹き飛ばして入れ直し」。ここを切り取ると 依存解決+ローカル展開性能 にフォーカスできるので、実感に近い差が観測できるのかな、と思いました。
モード | 削除対象 | グローバルキャッシュ | 主に測れるもの |
---|---|---|---|
system-cold | node_modules, lock + ~/.npm/_cacache / ~/.bun/install/cache | あり(毎回フル DL) | ネット速度+ CPU |
project-cold (本記事) | node_modules, lock | 残す | 依存解決 & 展開速度 |
cached | 何も消さない | 残す | 差分インストール処理 |
hyperfineの動き
warm-up (2 回) ← 本番前に “ネット DL” を肩代わり
├─ npm install
└─ bun install
─── 以下 run #1-5 が計測対象 ───
prepare: CLEAN ← ここで node_modules/ と lock を削除
run: npm install
prepare: CLEAN
run: bun install
...
・--warmup 1 を入れたおかげで、計測対象 20 回 (5×2×2) は ネット 0% / キャッシュ 100%。
・lock も消すので resolver のパフォーマンス差 もスコアに乗ります。
npm install --install-links と bun install --disable-cache を併用すると「完全キャッシュ無視」対決も出来ます。今回は再測定が大変なので割愛しましたが、誰か検証待ってます!
全選手入場!!!(測定環境一覧)
(別にnpmとbunが競うのであってこいつらが戦うわけでは)ないです。
Raspberry Pi 400
ちょっと前に秋月電子で買いました。買った直後に使い方を調べてほとんど変わらない値段で500が出てるのを知りました。
GMKTec G5
楽天で衝動買いしました。個人で使うWindowsの検証用の実機には向いてるんじゃないかな。ラズパイでクラスター組むのめんどくさそうなのでこれをもういくつか買うことを検討しています。
MacBook Pro 2018 Intel Core i5 RAM 8GB
今の大学に入った時にいただいたものです。Kキーの反応が鈍かったりカタログスペックでGMKTec G5に負けてる気もしますが愛着が沸いてるのとTouch Barが好きなので今でもたまにいじってます。
MacBook Pro 2023 Apple M2 Max RAM 96GB
メインPCです。プロセスがいっぱい動いてて測定時の干渉がやばそう。でも実際使うってなったら多分こいつで使うのでこれでも測定してみました。
測定中のあれこれ
Raspberry Pi 400 デフォルトのOSでBun動かない問題
Raspberry Pi 400 は工場出荷時32bit OSを積んでいるようで、Bunの実行ファイルが動きませんでした。64bit OSもあるので入れればええやんって話なのですが、ラズパイへのOS導入はmicroSDカードにOSイメージを書き込んでごちゃごちゃやるのが一般的なようで、microSDスロットがある機器なんて持ってたっけ...とまごついていたところ
たまたまその場にあったGMKTec G5にあった!!
64bit OSをぶちこんで解決です。
MacBookPro 2018のOS古すぎる問題
MacBookPro2018でベンチを実行しようとしたところ
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Preferences.
If that doesn't show you any updates, run:
sudo rm -rf /Library/Developer/CommandLineTools
sudo xcode-select --install
Alternatively, manually download them from:
https://developer.apple.com/download/all/.
You should download the Command Line Tools for Xcode 13.2.1.
とか言われたのでアップデートを試みたところ
ばかでかインストールを推奨されて測定が翌日に持ち越しになりました。
測定結果一覧
Machine | Project | npm cold | bun cold | Speed-up | npm cached | bun cached | Speed-up |
---|---|---|---|---|---|---|---|
GMKtec g5 | hono-app | 1.61s | 0.52s | ×3.1 | 1.638s | 0.504s | ×3.3 |
GMKtec g5 | next-app | 1.72s | 0.35s | ×5.0 | 1.830s | 0.343s | ×5.3 |
GMKtec g5 | remix-app | 3.10s | 0.94s | ×3.3 | 2.971s | 0.945s | ×3.1 |
Raspberry Pi 400 | hono-app | 27.78s | 0.37s | ×76.0 | 2.038s | 0.025s | ×81.6 |
Raspberry Pi 400 | next-app | 44.32s | 1.69s | ×26.2 | 2.532s | 0.029s | ×86.7 |
Raspberry Pi 400 | remix-app | 58.44s | 1.00s | ×58.5 | 5.438s | 0.060s | ×90.4 |
MacbookPro 2018 | hono-app | 13.11s | 2.59s | ×5.1 | 0.898s | 0.034s | ×26.2 |
MacbookPro 2018 | next-app | 14.37s | 2.97s | ×4.8 | 0.971s | 0.030s | ×32.5 |
MacbookPro 2018 | remix-app | 16.88s | 2.19s | ×7.7 | 1.731s | 0.059s | ×29.5 |
MacbookPro 2023 | hono-app | 6.76s | 1.70s | ×4.0 | 0.636s | 0.013s | ×50.0 |
MacbookPro 2023 | next-app | 8.62s | 2.07s | ×4.2 | 0.735s | 0.014s | ×54.1 |
MacbookPro 2023 | remix-app | 9.04s | 2.13s | ×4.2 | 1.176s | 0.033s | ×36.1 |
GMKtec g5ではSpeed-upが限定的で、Raspberry Pi 400ではSpeed-upが顕著などと、環境によって大きく差が出ました。次の章で解釈していきましょう。
結果の解釈
全般的な高速化の程度について
・「cold(node_modules と lock を空にする)」でも平均 3〜7 倍、
・「cached(グローバルキャッシュ 100 % 利用)」では 30〜80 倍 ——
表が示すとおり、ほぼすべての環境で bun install
が npm install
を大きく上回りました。
主な理由は次の 3 点です。
-
依存解決の並列化
Bun は Zig 製ランタイム内で lock 解決をマルチスレッド化。npm は JS 実装 + シングルスレッドのため、特に低クロック CPU で差が開く。 -
アーカイブ展開の高速ストリーミング
.tgz
展開を mmap 系 API で一度に処理 → 小ファイル大量展開でも I/O 待ちが少ない。 -
ファイル操作回数の削減
Bun はハードリンク/シンボリックリンクを積極利用し、fs.write/rename
系のシステムコールを最小に抑制。
GMKtec G5 でキャッシュ利用時の高速化が限定的な理由
・高速 NVMe SSD がボトルネックを打ち消し、npm でも I/O 待ちが少ない
・CPU が 4C/4T と少なく、Bun のマルチスレッドが飽和しやすい
Raspberry Pi 400 でキャッシュ時の高速化が顕著な理由
・microSD のランダム I/O が遅い → npm は小ファイル書込み地獄、Bun はリンク主体で圧勝
おわりに
こういうベンチマーク系の実験は初めてやったのでだいぶガバガバな検証となりましたが、GMKtec G5やRaspberry Pi 400で対照的な面白い結果が出てとりあえず満足してます。理論上CPUの並列性能が高くてI/O性能が低い環境ほど差が出そうですねえ。
こういう検証系の記事は自分の勉強にもなるので今後も上げていきたいなーと思ってます。読んでいただいてありがとうございました!追加の検証や考察などがある方はコメントしていただけると嬉しいです!
Discussion