パフォーマンス
実行ティア
zwasm は階層型実行を採用しています:
- インタープリタ: すべての関数はレジスタ IR として開始され、ディスパッチループで実行されます。起動が速く、コンパイルのオーバーヘッドがありません。
- JIT (ARM64/x86_64): ホットな関数は、呼び出し回数またはバックエッジ回数がしきい値を超えるとネイティブコードにコンパイルされます。
JIT が発動する条件
- 呼び出しのしきい値: 同じ関数が約8回呼び出された後
- バックエッジカウント: ホットなループは JIT をより早くトリガーします(ループの反復回数がしきい値にカウントされます)
- 適応型: しきい値は関数の特性に基づいて調整されます
JIT コンパイルが完了すると、その関数への以降のすべての呼び出しはインタープリタをバイパスし、ネイティブマシンコードを直接実行します。
バイナリサイズとメモリ
| 指標 | 値 |
|---|---|
| バイナリサイズ (ReleaseSafe) | 約 1.4 MB |
| ランタイムメモリ (fib ベンチマーク) | 約 3.5 MB RSS |
| wasmtime バイナリ(比較用) | 56.3 MB |
zwasm は wasmtime の約1/40のサイズです。
ベンチマーク結果
Apple M4 Pro 上で zwasm を wasmtime 41.0.1、Bun 1.3.8、Node v24.13.0 と比較した代表的なベンチマーク。 29 個中 16 個のベンチマークで wasmtime と同等以上の性能。29 個中 25 個が 1.5 倍以内。
| ベンチマーク | zwasm | wasmtime | Bun | Node |
|---|---|---|---|---|
| nqueens(8) | 2 ms | 5 ms | 14 ms | 23 ms |
| nbody(1M) | 22 ms | 22 ms | 32 ms | 36 ms |
| gcd(12K,67K) | 2 ms | 5 ms | 14 ms | 23 ms |
| tak(24,16,8) | 5 ms | 9 ms | 17 ms | 29 ms |
| sieve(1M) | 5 ms | 7 ms | 17 ms | 29 ms |
| fib(35) | 46 ms | 51 ms | 36 ms | 52 ms |
| st_fib2 | 900 ms | 674 ms | 353 ms | 389 ms |
メモリ使用量は wasmtime の 3〜4 分の 1、Bun/Node の 8〜10 分の 1 です。
全結果(29 ベンチマーク): bench/runtime_comparison.yaml
SIMD パフォーマンス
SIMD 操作は機能的に完全です(256 オペコード、仕様テスト 100%)が、レジスタ IR や JIT ではなくスタックインタプリタで実行されます。その結果、SIMD 実行は wasmtime の約 22 倍遅くなります。改善計画: レジスタ IR の v128 拡張、その後選択的な JIT NEON/SSE エミッション。
ベンチマーク手法
すべての測定は hyperfine を使用し、ReleaseSafe ビルドで行っています:
# クイックチェック(1回実行、ウォームアップなし)
bash bench/run_bench.sh --quick
# 完全な測定(3回実行、1回ウォームアップ)
bash bench/run_bench.sh
# 履歴に記録
bash bench/record.sh --id="X" --reason="description"
ベンチマークレイヤー
| レイヤー | 数 | 説明 |
|---|---|---|
| WAT micro | 5 | 手書き: fib, tak, sieve, nbody, nqueens |
| TinyGo | 11 | TinyGo コンパイラ出力: 同じアルゴリズム + 文字列操作 |
| Shootout | 5 | Sightglass shootout スイート (WASI) |
| Real-world | 6 | Rust, C, C++ を Wasm にコンパイル (行列、数学、文字列、ソート) |
| GC | 2 | GC プロポーザル: 構造体アロケーション、木の走査 |
CI によるリグレッション検出
PR は自動的にパフォーマンスリグレッションがチェックされます:
- 6つの代表的なベンチマークがベースブランチと PR ブランチの両方で実行されます
- いずれかのベンチマークが20%以上リグレッションした場合、失敗となります
- 同一ランナーにより公平な比較が保証されます
パフォーマンスのヒント
- ReleaseSafe: 本番環境では必ず使用してください。Debug は5〜10倍遅くなります。
- ホットな関数: 頻繁に呼び出される関数は自動的に JIT コンパイルされます。
- Fuel 制限:
--fuelは命令ごとにオーバーヘッドが加わります。信頼できないコードにのみ使用してください。 - メモリ: リニアメモリを持つ Wasm モジュールはガードページを割り当てます。初期 RSS はモジュールサイズに関係なく約 3.5 MB です。