Vize

パフォーマンス

⚠️ 進行中の作業:Vize は積極的に開発中であり、まだ運用環境で使用する準備ができていません。ベンチマークの数値は開発ビルドによるものであり、変更される可能性があります。

Vize は、Rust のゼロコスト抽象化とネイティブ マルチスレッドを活用することで、標準の JavaScript ベースの Vue コンパイラと比較して大幅なパフォーマンスの向上を実現します。スピードはあればいいものではなく、開発者のエクスペリエンスの前提条件です。

ベンチマーク環境

以下の過去の数値は、ローカルのワークステーションで取得されたものです。再現可能な CI ホスト型の場合 リリース ノートやドキュメントの更新に適した番号を使用するには、 Blacksmith ベンチマーク スナップショット ツール ベンチマーク ワークフローによって生成されました。

機械 MacBook Pro (M2 Max、12 コア、96 GB RAM)
OS macOS 15.3.2 (ダーウィン 24.3.0)
Node.js v24.14.0
ヴィート v8.0.0 (ロールダウン)
ビュー v3.6.0-ベータ.10

ベンチマーク: 15,000 SFC ファイル

  • *15,000 個の Vue SFC ファイル**のコンパイル (合計 36.9 MB):

@vue/コンパイラ-sfc ヴィゼ スピードアップ
シングルスレッド 9.35秒 3.47秒 2.7x
マルチスレッド 4.08秒 353ミリ秒 11.6x
コンパイラー sfc ST と Vize MT 9.35秒 353ミリ秒 26.0x

シングルスレッドの改善は、Rust のゼロコスト抽象化 (GC なし、JIT ウォームアップなし、キャッシュに優しいメモリ レイアウト) から来ています。マルチスレッドの改善は、CPU コア数にほぼ直線的にスケールする Rayon のワークスチール スレッド プールによるものです。

ネイティブのバッチ スケーリング動作

ファイル Vize バッチ (1 スレッド) Vize バッチ (12 スレッド) 並列高速化
100 25ミリ秒 3ミリ秒 8.5倍
1,000 243ミリ秒 26ミリ秒 9.4倍
5,000 1.25秒 128ミリ秒 9.7倍
15,000 3.75秒 373ミリ秒 10.1倍

これらのネイティブ バッチ番号には、ファイルの読み取りが含まれます。小さなバッチでは固定オーバーヘッドが大半を占めます。この 12 コア マシンでは、より大きなバッチの並列速度が約 10 倍に落ち着きます。

なぜ錆びるのか?

ゼロコストの抽象化

Rust の所有権モデルにより、ガベージ コレクションの一時停止が不要になります。コンパイラーは、アリーナ割り当て (vize_carton) を通じて AST ノードを処理し、ノードごとのヒープ割り当てを回避します。これはつまり:

  • GC 一時停止なし— V8 ベースのコンパイラでは、ガベージ コレクションにより、予測できない遅延のスパイクが発生する可能性があります。 Vize には GC オーバーヘッドがありません。

  • JIT ウォームアップなし— V8 の JIT コンパイラーはホット パスを最適化するのに時間がかかります。 Vize は最初の命令から全速力で実行されます。

  • 予測可能なパフォーマンス— Rust の事前コンパイルは、V8 の最適化ヒューリスティックに依存せず、実行間でパフォーマンスが一貫していることを意味します。

ネイティブ マルチスレッド

Vize はデータ並列コンパイルに Rayon を使用します。各 SFC ファイルは個別にコンパイルされるため、ワークロードは恥ずかしいほど並列になります。 Rayon のワークスチール スケジューラは、最適なコア使用率を保証します。

// Simplified: parallel compilation of all .vue files
files.par_iter().map(|file| {
    let arena = Bump::new();
    let ast = parse(file, &arena);
    let analyzed = analyze(ast, &arena);
    compile(analyzed, &arena)
}).collect()

ワークスチールアプローチとは、あるファイルが他のファイルよりも大幅に大きい場合、アイドル状態のスレッドがビジースレッドのキューから作業を奪い、ほぼ完璧な負荷分散を維持することを意味します。

効率的なメモリレイアウト

Rust の構造体レイアウトと列挙型判別式はコンパクトです。 vize_relief の AST 表現はキャッシュに適しており、メモリ帯域幅のボトルネックを軽減します。

  • 列挙型の判別式— Rust の列挙型は、判別式に適合する最小の型にサイズ設定されます。 20 個のバリアントを持つ NodeKind は、ヒープに割り当てられた文字列ではなく、単一バイトを使用します。

  • 構造体のパッキング— Rust は、最適な位置合わせのために構造体フィールドの順序を自動的に変更し、パディングバイトを最小限に抑えます。

  • オブジェクト ヘッダーなし— JavaScript オブジェクト (プロトタイプ チェーン、プロパティ マップ、および隠しクラス ポインターを運ぶ) とは異なり、Rust 構造体はオーバーヘッドのない純粋なデータです。

実行時のオーバーヘッドなし

V8 で実行される JavaScript ベースのコンパイラーとは異なり、Vize はネイティブ コードに直接コンパイルします。 JIT ウォームアップ、ガベージ コレクター、イベント ループ競合はありません。コンパイラ バイナリは、静的にリンクされた単一の実行可能ファイルであり、フルスピードで起動および実行されます。

パフォーマンスのためのアーキテクチャの選択

アリーナの割り当て

vize_carton は、bumpalo を使用して AST ノードのバンプ アロケーターを提供します。これはつまり:

  • 割り当ては O(1)— ポインタを前方に移動するだけです。フリーリストのトラバーサルや断片化の管理はありません。

  • 割り当て解除は O(1)— コンパイルが完了したら、アリーナ全体を一度に削除します。ノードごとの割り当て解除のオーバーヘッドはありません。

  • メモリの局所性が優れています— ノードがメモリ内に連続してパックされ、ツリー トラバーサル中の L1/L2 キャッシュ ヒットが最大化されます。

これは、到達可能なオブジェクトを追跡し、メモリを定期的に圧縮する必要がある V8 の世代別ガベージ コレクターに比べて、基本的な利点です。

ストリーミングトークナイザー

vize_armature のトークナイザーは入力をバイト ストリームとして処理するため、中間トークン配列を構築する必要がありません。パーサーはトークンを遅延的に消費します。各トークンはオンデマンドで生成され、すぐに消費されます。これにより、ピーク時のメモリ使用量が削減され、キャッシュの動作が改善されます。

ストリングインターン

共通文字列 (ディレクティブ名、属性名、HTML タグ名) は、compact_str および完全ハッシュ テーブル (phf) を介してインターンされます。これはつまり:

  • 文字列比較は、文字ごとの比較 (O(n)) ではなく、ポインタ比較 (O(1)) です。

  • 重複する文字列は単一の割り当てを共有します

  • 既知の文字列のハッシュ ルックアップはコンパイル時に計算されます

インクリメンタルコンパイル

Vite プラグイン (@vizejs/vite-plugin) はファイルレベルのキャッシュを使用します。開発中には変更されたファイルのみが再コンパイルされ、HMR 遅延が最小限に抑えられます。キャッシュ キーはファイル コンテンツのハッシュであり、変更されていないファイルが再コンパイルされないようにします。

ベンチマーク: Linter — Patina vs eslint-plugin-vue

リンティング15,000 Vue SFC ファイル:

eslint-プラグイン-vue (ST) ヴィゼ パティナ (ST) スピードアップ eslint-プラグイン-vue (MT) ヴィゼ パティナ (MT) スピードアップ eslint ST 対 Vize MT
時間 45.08秒 4.02秒 11.2x 16.38秒 784ミリ秒 20.9x 57.5x

再現するには、vp run --workspace-root bench:lint を実行します。

タイプ認識型 lint プロファイル

タイプ認識リンティングは、コストが集中する傾向があるフェーズ (SFC 解析、 クロッキー分析、仮想 TypeScript 生成、テンプレート クエリ コレクション、および Corsa プローブ。いつ 複数のテンプレートに基づく型認識ルールが有効になっており、Patina はテンプレート式を収集し、 テンプレート Corsa プローブ フェーズの前の 1 つの AST ウォークでの Promise クエリ。クエリコレクションも共有 OXC 式は安全でないテンプレートとフローティング Promise チェックを解析するため、1 つのテンプレート式 両方のルールが有効な場合、重複した解析コストは発生しません。

vize lint --profile --preset opinionated src を実行して、ローカル プロジェクト内のこれらの行を表示します。の プロファイル レポートには、経過時間カバレッジ、累積的なデータをチェックする厳密な監査セクションも含まれています。 ホットファイルと内部をリストする前に、ワーカー時間、低速しきい値ヒット、キャプチャされた内部スパンを確認します。 操作。ホットファイル行はステージごとのシェアとスループットを示し、操作行は支配的なフラグを示します スパンまたは最大/平均スパイク。

ベンチマーク: フォーマッタ — グリフと Prettier

  • *15,000 個の Vue SFC ファイル**のフォーマット:

プリティア (CLI) ヴィゼグリフ(ST) スピードアップ ヴィゼグリフ(MT) Prettier CLI と Vize MT
時間 101.20秒 2.97秒 34.1x 835ミリ秒 121.2x

再現するには、vp run --workspace-root bench:fmt を実行します。

ベンチマーク: 型チェッカー — canon 対 vue-tsc

現在の Corsa-backed 診断パスを使用して500 個の生成された Vue SFC ファイルをタイプ チェックします。

vue-tsc (ST) ヴィゼカノン (ST) スピードアップ vue-tsc (MT) ヴィゼカノン (MT) スピードアップ vue-tsc ST と Vize MT
時間 4.38秒 511ミリ秒 8.6x 4.41秒 493ミリ秒 8.9x 8.9x
料金 114 ファイル/秒 979 ファイル/秒 113 ファイル/秒 1.0k ファイル/秒

注意:Vize canon はまだ開発初期段階にあり、Corsa を利用した診断パスは vue-tsc の忠実度にまだ追いついていません。これらの測定値は、プロジェクト セッション フォールバックを備えた現在の CLI ファースト ネイティブ実装を反映しており、診断カバレッジとパリティが向上するにつれて変化します。

この簡単なベンチマークを再現するには、cargo build --release -p vize の後に node bench/check.ts 500 を実行します。

タイプチェッカープロファイル

500-SFC プロファイル フィクスチャは、Corsa CLI コマンド内でのほとんどの所要時間を維持しますが、インポート リライト高速パスにより、Vue 指定子のないファイルに対する以前の OXC 解析コストが削除されます。

メトリック 現在
canon.import.rewrite.vue 26.77ミリ秒 2.45ミリ秒
生成された最大の仮想 TS 15,401B 14,414B
プロファイルの合計経過時間 1.88秒 668ミリ秒
Corsa 診断フェーズ 1.67秒 482ミリ秒
Corsa CLI 解析 該当なし 10.41ミリ秒

Rust 側の virtual project フェーズ — ファイルごとの SFC 解析、クロッキー解析、 仮想 TS の生成とインポートの書き換え — rayon のスレッド全体で扇動されます VirtualProject::register_paths内のプール。各 .vue ファイルは独立しています ワークスペース オプションが解決されると、単一のバッチが並列化されます。 きれいに。 1,000-SFC フィクスチャでは、位相が約 71 ms から約 25 ms に低下します。 コルサも発動する。

診断を多用する e2e フィクスチャ

bench/check.ts は、フィクスチャが存在する場合、tests/_fixtures/_git/npmx.dev アプリも測定します。これにより、実際のアプリケーション フィクスチャ上の診断マッピング パスが取得されます。

治具 ソース SFC ファイル 仮想ファイル 診断 ヴィゼカノン
npmx.dev アプリ 134 226 1,053 1.94秒

このフィクスチャの現在のプロファイルでは、CLI 診断解析が約 7 ミリ秒に維持されます。現在、ほとんどの時間は Corsa CLI コマンド自体に費やされています。フレームワークの自動インポート スタブを 1 つのアンビエント ファイルにホイストすると、生成される最大の仮想 TS ファイルも約 275 KB から 144 KB に削減されました。

ベンチマーク: Vite プラグイン — @vizejs/vite-plugin 対 @vitejs/plugin-vue

  • *1,000 個の Vue SFC インポート**を含む Vite ビルド (すべて 1 つのエントリでインポート):

@vitejs/plugin-vue @vizejs/vite-plugin スピードアップ
ビルド時間 957ミリ秒 479ミリ秒 2.0x

注: @vizejs/vite-plugin は Vue SFC コンパイル手順のみを置き換えます。パフォーマンスの違いは完全にその部分から生じます。依存関係の解決、モジュール グラフの構築、バンドル (ロールダウン)、およびその他すべての Vite 内部は @vitejs/plugin-vue と同一です。純粋なコンパイルのパフォーマンスについては、上記の コンパイラ ベンチマーク を参照してください。 @vizejs/vite-plugin は、ネイティブ マルチスレッド コンパイルを使用して .vue ファイルを積極的にプリコンパイルします。これにより、より高速な HMR も可能になります。

再現するには、vp run --workspace-root bench:vite を実行します。