Codex WindowsアプリがWSLで重い原因:EISDIR監視ループとMCP蓄積を実測¶
対象 / ポイント
対象: WSL2上のGitリポジトリをWindows版Codexで開き、継続的なCPU・メモリ増加を調べたい開発者。
ポイント:
- 実機の直近80ログから
EISDIRを341,602件検出した - WSL側には22個のMCPプロセスが残り、合計約1.28GBのRSSを使用していた
- Windows側の監視とチャット単位のMCP保持を分けて対処する
WSL2上のリポジトリをWindows版Codexで使い続けるうちに、操作が少しずつ重くなった。 最初はWSLのI/Oを疑ったが、ログにはGitパスの監視エラーが連続し、WSL内にはチャットごとのMCP(Model Context Protocol)プロセスが残っていた。
重さの正体は1つではなかった。 Windows側のファイル監視ループと、WSL側のMCPランタイム保持を分けて追うと、CPU・ログ・メモリが増えた理由を説明できる。
調査環境と確認できた範囲¶
数値は2026年7月14日、実際に動作が重くなったPCから採取した。 同じ条件で追試できるようにOSやバージョンは残し、ユーザー名、リポジトリ名、タスク識別子だけを伏せている。
| 項目 | 内容 |
|---|---|
| OS | Windows 11 x64 |
| Codex Windowsアプリ | 26.707.9981.0 |
| アプリのエージェント | WSLモード |
| WSL内のCodex CLI | 0.144.4 |
| WSL | WSL2 / Ubuntu 26.04 |
| リポジトリ | WSLのLinuxファイルシステム上 |
| Windowsから見たパス | \\wsl$\Ubuntu-26.04\home\<user>\<repository> |
公式ドキュメントでは、WindowsアプリのエージェントをWSL2で実行するモードが案内されている1。 今回の環境はすでにそのWSLモードを使っていた。 それでもWindows側のGit監視とWSL側のMCP保持が併存した点が、今回の診断で重要になる。
一方、Get-Location、Get-Date、単純な文字列出力は約0.2〜0.3秒で終わった。 ローカルコマンドが数分止まる症状は再現していない。 ここで扱うのはバックグラウンドの継続負荷であり、別の遅延まで同じ原因とはみなさない。
原因1:WSLのGitパスでEISDIR監視が再試行される¶
最初の負荷源は、Windows側のGitワークスペース監視だ。 Codexのログには、WSL上の.gitディレクトリを監視しようとして失敗する警告が大量に残っていた。
[git-repo-watcher] Failed to watch git path
errorCode=EISDIR
errorMessage="EISDIR: illegal operation on a directory,
watch '\\\\wsl$\\Ubuntu-26.04\\home\\<user>\\<repository>\\.git'"
EISDIRは、対象がディレクトリであるため要求した操作を実行できない場合に返るエラーだ。 この環境では、Windows側のNode.jsファイル監視がWSLのGitパスで失敗していた。
直近80ログで34万件を超えた¶
直近80個のログを走査した結果、同じエラー系列が異常な密度で記録されていた。
| パターン | 検出件数 |
|---|---|
EISDIR | 341,602件 |
git-repo-watcher | 341,874件 |
git-init-watcher | 387件 |
7月14日の複数ログでは、1ファイルあたり約9,000件のEISDIRが記録され、ログは約10MB単位でローテーションしていた。 7月13日の別ログでは、git-init-watcherの失敗がほぼ5秒間隔で並んでいた。
この再試行間隔とエラー形式は、openai/codexのIssue #32695で報告された現象と一致する2。 同IssueはWindows 11とWSL2でEISDIR後の監視が約5秒間隔で続く問題を記録しており、2026年7月14日時点でOpenだ。 実測したアプリはIssueの報告版より新しいため、少なくとも26.707.9981.0では同系統の負荷が残っている。
ログ量が多いこと自体より、永久エラーを再試行する処理がアプリの稼働中に続くことが問題だ。 ログ削除だけでは、次の書き込みを止められない。
原因2:開いたチャットごとにMCPプロセスが保持される¶
2つ目の負荷源は、WSL内のapp-serverが保持するMCPプロセスだ。 1つのapp-server配下に、アプリ管理のnode_repl MCPが複数世代残っていた。
| 項目 | 実測値 |
|---|---|
| MCPプロセス合計 | 22個 |
server.cjs | 11個 |
server.mjs | 11個 |
| MCP合計RSS | 約1,283MB |
| WSL app-server本体 | 約337MB |
各プロセスの経過時間は異なり、同時に一括起動された形ではなかった。 チャットを開いた時刻に応じてMCPの組が増え、以前の組もapp-serverの配下に残ったと考えるのが自然だ。
Issue #32154は、既存チャットを切り替えるだけで、未ロードのチャットごとに新しいMCPプロセス群が起動するWindows/WSL2環境を報告している3。 同Issueの制御実験では、ユーザー設定のstdio MCPを無効にすると保持MCPのRSSは約96%減ったが、デスクトップUIの停止は残った。 つまり、MCPのメモリ増幅とチャット表示経路の重さは、重なって見えても同一ではない。
今回残っていた22プロセスはユーザーが追加したMCPではなく、アプリ管理のnode_replだった。 そのため「外部MCPをすべて無効化すれば解決する」とは言えない。 機能を失う設定変更より、先にWindowsアプリを経由しないCLI運用と開くチャット数を見直すほうが安全だ。
CPUとログ容量への影響¶
Windows側のCodexプロセス群は、短時間の測定でも論理コア約1個分のCPU時間を使っていた。 3秒間でCPU時間が約3.08秒、別の5秒間では約5.64秒増加した。
ただし、これは完全なアイドル条件をそろえたベンチマークではない。 再起動直後、WSLプロジェクトを開いた後、MCPを減らした後を同じ条件で測定しなければ、原因別のCPU寄与率までは決められない。
ログ容量への影響は明確だった。
| 対象 | 容量 |
|---|---|
| Codexログ全体 | 約474MB |
| 7月14日分 | 約137MB |
| 7月14日のログ数 | 21ファイル |
ただし、この3つを1本の因果関係で結ぶのは早い。 CPU、ログ、MCPの値は同時に増えていたが、どれか1つが残りのすべてを引き起こしたとは証明できていない。 監視エラーとMCP保持が同じ環境で併存した、というのが今回確認できた範囲だ。
5分でできる切り分け¶
診断では、Windows側のログとWSL側のプロセスを分けて見る。 実パスやユーザー名を公開しないまま、エラー系列とプロセス数を確認できる。
Windows側で監視エラーを探す¶
PowerShellで直近ログを絞り、EISDIRとGit watcherだけを検索する。
$pkg = Get-AppxPackage OpenAI.Codex
$root = Join-Path $env:LOCALAPPDATA `
"Packages\$($pkg.PackageFamilyName)\LocalCache\Local\Codex\Logs"
$files = Get-ChildItem $root -Recurse -File |
Sort-Object LastWriteTime -Descending |
Select-Object -First 30
Select-String -Path $files.FullName `
-Pattern 'EISDIR|git-init-watcher|git-repo-watcher'
数件だけなら一時エラーの可能性がある。 同じパスで数秒ごとに増え続けるなら、監視の再試行を疑う。
WSL側でMCPの世代数を見る¶
次に、app-serverとNodeプロセスの親子関係、RSS、経過時間を確認する。
wsl -d Ubuntu-26.04 -- bash -lc `
"ps -eo pid,ppid,%cpu,%mem,rss,etime,cmd --sort=-rss |
rg -i 'codex|mcp|node' | head -50"
同じコマンド名が複数あり、経過時間がチャット切り替えの時刻と対応するなら、チャット単位の保持を疑う。 プロセス数だけでなく、親PIDと合計RSSも記録すると再起動前後を比較しやすい。
回避策はWindowsアプリの監視経路を外す¶
今回の環境はすでにWSLモードだったため、エージェント設定の切り替えだけでは改善しなかった。 次に外すべきなのは、Windowsアプリが\\wsl$経由でワークスペースを管理する経路そのものだ。
1. WSLネイティブのCodex CLIへ切り替える¶
WSLのリポジトリをLinux側だけで扱うには、WSLシェルからCodex CLIを起動する。 公式のWSLガイドも、Linuxホーム配下にリポジトリを置き、WSL内でcodexを実行する手順を案内している4。
この方法はWindowsアプリの\\wsl$監視経路を作業フローから外せる。 今回のようにWSLモードでも監視ループとMCP保持が続く場合、デスクトップUIを手放せるなら最も直接的な回避策だ。
2. GUIが必要ならWindowsネイティブcloneへ切り替える¶
Windowsアプリを使い続けるなら、C:\src\...などへリポジトリをcloneし、エージェントもWindowsネイティブで動かす。 公式ドキュメントも、Windowsネイティブのエージェントを使う場合はWindows側にプロジェクトを置く構成がより安定すると案内している1。
必要なときだけWSLから/mnt/c/...として参照する。 Linux固有のツールチェーンが必須なら、この構成よりCLI運用を優先する。
\\wsl$をネットワークドライブへ割り当てても、監視対象の実体は変わらない。 Issue #32695でもマップドライブ経由の再現が報告されているため、ドライブ文字への置換は回避策にならない2。
3. チャットとstdio MCPを必要最小限にする¶
アプリで複数の既存チャットを順番に開くほど、MCPランタイムが増える可能性がある。 使わないチャットを次々に開かず、負荷が増えたらアプリを完全終了してプロセスが解放されたか確認する。
ユーザー設定のstdio MCPが多い場合は、不要なものだけ無効化する。 一方、今回のようにアプリ管理MCPが中心なら、設定ファイルを直接削る前にWindowsアプリを介さないCLI運用を試す。
効果が期待しにくい対策¶
次の対策は一時的に数値を下げても、負荷を生む経路そのものは残る。
- ログだけを削除する: ディスク容量は戻るが、監視の再試行は続く
- WSLのメモリ上限だけを下げる: 上限到達を早めるだけで、MCPプロセス数は減らない
- ネットワークドライブへ割り当てる: WSLパスの監視方式は変わらない
- Codex CLIだけを再インストールする: Windowsアプリ同梱app-serverの挙動は更新されない
- すべての遅延を同じIssueへ結び付ける: 今回は数分停止や固定遅延を再現していない
根本修正には、永久的な監視エラーを打ち切る処理と、非アクティブなチャットからMCPランタイムを解放するライフサイクル管理が必要だ。 利用者側では、その修正を待ちながらOS境界と同時チャット数を減らすことになる。
まとめ:UI上のチャット数をリソース数として扱う¶
今回の環境では、EISDIR監視ループとチャット単位のMCP保持を同時に確認した。 前者はWindows側のCPUとログ、後者はWSL側のプロセス数とメモリを主に押し上げる。
実務上の優先順位は次のとおりだ。
- WSLリポジトリはWSLネイティブのCodex CLIで扱う
- GUIが必要ならWindows側へcloneし、Windowsネイティブのエージェントで開く
- 既存チャットとstdio MCPを必要最小限にし、増加量を再測定する
見落としやすいのは、デスクトップアプリのチャット一覧が単なる表示状態ではない点だ。 チャットがバックエンドのMCPランタイムを所有する設計では、開いたチャット数がそのままプロセスとメモリの予算になる。 修正が入るまでは、ログ件数、親子プロセス、RSSをセットで記録すると再発を早く見抜ける。
関連記事¶
ChatGPT desktop app for Windows: Windows Subsystem for Linux - OpenAI ↩↩
[App/Windows/WSL] git-init-watcher retries permanent EISDIR on workspace root every five seconds - openai/codex #32695 ↩↩
Windows/WSL2: Desktop retains one eager MCP stack per opened chat and replays history during navigation - openai/codex #32154 ↩