Tauri v2アプリに搭載したgit diffの表示が遅い原因を調査した
症状
自作のClaude Codeセッションマネージャ(Tauri v2 + React)に、Git Diffを確認できるUIを作っていました。 しかし、パネルを開くと表示が異常に遅いという問題がありました。
調査
ボトルネックの候補は3つありました。
- Rust側:
git diffコマンドの実行 - フロントエンド: diffのパース・DiffViewレンダリング
- ファイル監視: パネル表示時に開始する
watch()
各所に performance.now() / std::time::Instant でログを仕込んで計測したところ、
[DiffPanel] getGitDiff IPC: 52.0ms
[DiffPanel] parseUnifiedDiff: 0.0ms
[DiffSection] render: 15.0ms
[DiffPanel] watch() ready: 1654.0ms ← ここ
IPCは52ms、レンダリングは15ms。watch() だけ1.6秒かかっていたことがわかりました。
原因
Tauri plugin-fsの watch() を recursive: true でプロジェクトルートに対して呼んでいたことが原因でした。
watch(
project.path,
() => {
fetchDiff(true);
},
{ recursive: true, delayMs: 500 },
);
これは node_modules、target、.git など大量のファイルを含むディレクトリもすべて再帰的にスキャンするので、ファイル数が多いプロジェクトほど遅くなるようです。
修正
watch() をやめて2秒間隔のポーリングに変更。
const pollInterval = setInterval(() => {
fetchDiff(true);
}, 2000);
git diff のIPC呼び出しは約50msなので、2秒ごとのポーリングでも負荷は軽微。ファイル監視と違い、ネストされたディレクトリの変更も確実に検知できる。
.git ディレクトリだけ監視する案
最初は .git ディレクトリだけを watch() すれば高速になると考えたが、Tauriのfsプラグインの権限スコープで弾かれた。
forbidden path: .../.git, maybe it is not allowed on the scope
for `allow-watch` permission in your capability file
動的なプロジェクトパスに対して .git を許可するのは設定が煩雑になるため、ポーリング方式を採用した。
まとめ
- ファイル監視の
recursive: trueは便利だが、node_modules等を含むディレクトリでは重大なパフォーマンス問題になる - 計測ログを各レイヤーに仕込むことで、1.6秒のボトルネックを即座に特定できた
git diffが十分高速(50ms)なら、ファイル監視よりポーリングの方がシンプルで確実