Perry vs Bun
Bun はオールインワンの JavaScript / TypeScript ランタイム、バンドラ、パッケージマネージャ、テストランナーであり、自身のランタイムをコードと一緒にバンドルすることで単一ファイルの実行ファイルも生成できます。Perry は別の道を選びました――TypeScript を LLVM 経由で直接ネイティブマシンコードにコンパイルします。バイナリの中に JavaScript エンジンはなく、ランタイムもなく、小さなネイティブ実行ファイルがあるだけです。Bun と Perry は「TS から単一バイナリ」という出力では重なりますが、そのバイナリの中に JavaScript エンジンを入れるべきかどうかで意見が分かれています。
Bun とは?
Bun は Zig で書かれた高速なオールインワンの JavaScript / TypeScript ツールキットです。`.ts` ソースを直接実行し(事前コンパイル不要)、JS エンジンには JavaScriptCore を採用、バンドラ・パッケージマネージャ・テストランナーも内蔵しています。`bun build --compile` は Bun ランタイムをアプリケーションと一緒に単一の実行ファイルへバンドルします。Bun は x64 と arm64 上の Linux、macOS、Windows をターゲットにしています。
Perry とは?
Perry は Rust で書かれたネイティブ TypeScript コンパイラです。TypeScript を LLVM 経由で直接ネイティブマシンコードへコンパイルします――JavaScript エンジンも、ランタイムも、JIT もありません。出力は単一のバイナリで、hello world で約 330 KB、Fastify サーバのような stdlib をフル活用したアプリでも ~48 MB 程度です。Perry は macOS、iOS、iPadOS、Android、Linux、Windows、watchOS、tvOS、WebAssembly、Web を含む 10 のプラットフォームをターゲットにしています。
並べて比較
| 機能 | Perry | Bun |
|---|---|---|
| 出力 | ネイティブマシンコード(LLVM) | あなたのコード + Bun ランタイムを 1 つのバイナリにバンドル |
| バイナリ内の JavaScript エンジン | デフォルトではなし。--enable-js-runtime でオプションの V8(+ ~15 MB) | JavaScriptCore(常時) |
| hello-world バイナリサイズ | ~330 KB | ~50–100 MB(Bun ランタイムを含む) |
| JIT | なし(AOT コンパイル) | あり(JavaScriptCore JIT) |
| モバイルターゲット(iOS、Android) | あり――UIKit / JNI 経由のネイティブ UI | なし |
| ウォッチ / TV ターゲット | watchOS、tvOS、Wear OS | なし |
| ネイティブ UI ウィジェット | AppKit、UIKit、GTK4、Win32、JNI 経由で 25+ | なし(サーバ / CLI 中心) |
| npm エコシステム | 純粋な TS / JS パッケージはネイティブにコンパイル可能。それ以外はオプションの V8 経由 | Node 互換の npm をフルサポート |
| 安定性 | 1.0 未満(アルファ) | 安定版(1.x) |
| 実装言語 | Rust | Zig |
Perry が優れている点
- +バイナリが小さい――Perry の hello world は ~330 KB ですが、Bun の --compile による hello world は Bun ランタイムを含み数十 MB になります。
- +JavaScript エンジンのコストがありません。Perry でコンパイルされたバイナリにはインタプリタも JIT も入っておらず、TypeScript そのものが実行ファイルです。
- +モバイル、ウォッチ、TV。Perry は iOS、iPadOS、Android、watchOS、tvOS、WebAssembly にコンパイルできます。Bun はサーバ / デスクトップ専用です。
- +ネイティブ UI。Perry の perry/ui モジュールは実プラットフォームのウィジェット(macOS の AppKit、iOS の UIKit、Linux の GTK4、Windows の Win32、Android の JNI)にコンパイルされます。Bun に UI のストーリーはありません。
- +M1 Max 上で条件を揃えた計測(RUNS=11、v0.5.279、2026-04-25)の主要な計算系マイクロベンチで高速:fibonacci 318 ms 対 Bun 589 ms、object_create 1 ms 対 6 ms、nested_loops 18 ms 対 21 ms。完全な表は perry/benchmarks を参照してください。
- +動的型付けパックの JSON validate-and-roundtrip も高速:同じ 1 万件レコードのワークロードで Perry の遅延 JSON テープは中央値 75 ms、Bun は 259 ms です。
Bun が優れている点
- +1.x リリースを擁する成熟した安定ランタイム。Perry は 1.0 未満です。
- +JSON parse-and-iterate(すべての値に触れる)が高速:同じワークロードで Bun 254 ms 対 Perry 466 ms(中央値)――反復が強制されると Perry の遅延テープはショートカットできません。
- +標準で Node 互換の完全な npm エコシステムが使えます。Perry は一部をネイティブ実行し、残りはオプションの組み込み V8 にフォールバックします。
- +テストランナー、バンドラ、パッケージマネージャを内蔵。Perry はコンパイラであり、周辺ツールは別物です。
- +ホットな内ループを含む反復重視のコードでは、JIT がウォームアップ後に AOT を上回ることがあります。Perry に JIT はありません。
- +`loop_data_dependent` では実行ごとのノイズの範囲内で Perry と互角(232 ms 対 235 ms)――どちらのコンパイラも並べ替えられない、純粋に畳み込み不能な f64 カーネルです。出典:perry/benchmarks RUNS=11。
Perry を選ぶべきとき
バイナリサイズが重要なとき(モバイル配布、組込み用途、高速なコールドスタート)、ひとつの TypeScript コードベースからモバイル / ウォッチ / TV へ出荷したいとき、ネイティブ UI ウィジェットが欲しいとき、または出荷物の中に JavaScript エンジンをまったく入れたくないときに Perry を選んでください。
Bun を選ぶべきとき
今すぐ安定した成熟したランタイムが必要なとき、npm の完全互換が譲れないとき、ランタイム + バンドラ + パッケージマネージャ + テストランナーを 1 つのツールで済ませたいとき、または長時間稼働するワークロードでの JIT ウォーム後のパフォーマンスがコールドスタートのサイズより重要なときは Bun を選んでください。
結論
Bun と Perry はどちらも TypeScript プログラムを単一バイナリとして出荷できますが、答えている問いが異なります。Bun のバイナリには Bun ランタイムが含まれ、JIT と Node 互換が効くバックエンド / CLI ワークロード向けに最適化されています。Perry のバイナリには JS エンジンが含まれず、サイズ、コールドスタート、モバイル、ネイティブ UI のために最適化されています。サーバを出荷するなら今は Bun のほうが実績豊富です。ネイティブアプリを出荷する、あるいはバイナリサイズを気にするなら、Perry はその用途のために作られています。