← ブログ一覧

Tauri v2アプリに搭載したgit diffの表示が遅い原因を調査した

症状

自作のClaude Codeセッションマネージャ(Tauri v2 + React)に、Git Diffを確認できるUIを作っていました。 しかし、パネルを開くと表示が異常に遅いという問題がありました。

調査

ボトルネックの候補は3つありました。

  1. Rust側: git diff コマンドの実行
  2. フロントエンド: diffのパース・DiffViewレンダリング
  3. ファイル監視: パネル表示時に開始する 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_modulestarget.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)なら、ファイル監視よりポーリングの方がシンプルで確実