概要
- Bun はパッケージインストールが非常に高速
- npm/pnpm/yarn よりも圧倒的に少ないシステムコール数
- システムプログラミング的手法 で徹底的な最適化を実現
- Node.js由来の従来手法 の限界とBunの革新性
- 実際のベンチマーク で示される圧倒的な速度差
Bunのパッケージインストールが圧倒的に速い理由
- Bun はパッケージインストール時、 npmの約7倍、pnpmの約4倍、yarnの約17倍 の速度を実現
- 特に 大規模コードベース で顕著な高速化
- 従来の数分かかる作業が 数秒(ミリ秒) で完了
- 単なるベンチマークではなく、 システムレベルの最適化 による本質的な高速化
- パッケージインストール を「JavaScriptの問題」ではなく「システムプログラミングの問題」として捉える姿勢
Node.js時代の設計と現在のギャップ
- Node.js は2009年に登場し、 I/O待ち が主なボトルネックだった時代に最適化
- JavaScriptの イベントループ を活用し、非同期I/Oを効率化
- 2009年当時は ディスクシーク10ms、DBクエリ50-200ms、HTTPリクエスト300ms超 が当たり前
- サーバーはI/O待ちで CPUの95%を浪費 していた
- しかし現在は ハードウェア進化 により、I/O待ちよりも システムコールのオーバーヘッド が主なボトルネックに
システムコールの問題点
- アプリケーションがOSにアクセスするたびに システムコール が発生
- ユーザーモード と カーネルモード の切り替えは 1000-1500サイクル のオーバーヘッド
- 3GHz CPUで0.5マイクロ秒程度だが、 大量のシステムコール が発生すると膨大なCPU時間を消費
- 例えばReactインストールで 5万回以上のシステムコール が発生し、モード切り替えだけで数秒のCPU時間を浪費
パッケージマネージャーごとのシステムコール比較
- Bun: 165,743回(29.5k/秒)
- pnpm: 456,930回(18.6k/秒)
- npm: 996,978回(26.8k/秒)
- yarn: 4,046,507回(43.0k/秒)
- futexコール (スレッド同期用)もBunは極端に少ない(Bun: 762回、npm: 663,158回、yarn: 2,499,660回、pnpm: 116,577回)
Bunのアプローチと他ツールの違い
- npm/pnpm/yarn はすべて Node.js製 で、 libuv 経由でシステムコールを間接的に実行
- JavaScript→libuv→スレッドプール→カーネルモード→戻る、という複雑なパイプライン
- 各fs.readFileごとにスレッド同期やロック取得でfutexコール多発
- Bun は Zig製 で、 ネイティブコードから直接システムコール を実行
- 余計なランタイムやスレッドプール、イベントループを経由せず、最短経路でOSにアクセス
- その結果、 package.jsonファイルの読み込み速度 も圧倒的(Bun: 0.019ms/件、Node.js: 0.065ms/件)
Bunのインストール最適化事例
- DNS解決の非同期化 (macOS限定最適化)
- package.json解析中に並行してDNSルックアップを先行実行
- 依存関係解析やファイル操作 もすべてネイティブなシステムコールで高速処理
- Node.jsプロジェクトでもbun install利用可能 で、既存のエコシステムを壊さず高速化
まとめ
- Bunはシステムプログラミング的発想 でパッケージ管理を再定義
- 徹底したシステムコール削減 と ネイティブ最適化 で、従来のNode.js系パッケージマネージャーを圧倒
- 現代のハードウェア性能 をフル活用し、インストール体験を劇的に向上
- Node.js依存のツール設計 が抱える構造的な遅さを根本から解決するアプローチ