Sustained explorer.exe working-set growth with TortoiseGit recursive status cache enabled
0 reputation · 06 Dec 2022, 01:05 UTC
0 reputation · 06 Dec 2022, 01:05 UTC
Browsing a large Git working tree in File Explorer with TortoiseGit overlay icons enabled can produce sustained growth in the Windows shell process private working set. The documented failure condition points to the shell extension's recursive status cache rather than Git itself, particularly when the cache tracks a broad set of paths under default monitoring behavior.
The controlling setting is the Status cache mode under Icon Overlays, which can be set to None, Default, or Shell. Default moves the cache to the external TGitCache process, while Shell keeps it inside explorer.exe. An unresolved decision is when a cached status becomes stale after a file-system change, an index update, or a branch switch. Trusting the cache too long leaves incorrect overlays; invalidating too eagerly forces repeated scans that may amplify memory retention.
Version sensitivity adds uncertainty because overlay handler registration and TGitCache behavior have changed across releases, so behavior observed on one TortoiseGit and Git for Windows pair may not transfer to another. Narrowing Include and Exclude paths reduces the tracked path count, but the invalidation strategy remains the core variable.
What invalidation triggers should the recursive status cache use after a file-system change, an index update, or a branch switch to avoid stale overlays without forcing re-scans? How does the choice between Default and Shell cache placement change the memory-accounting tradeoff in a large working tree? Which version-specific behaviors need confirmation before comparing cache growth across different TortoiseGit releases?
The recursive status cache invalidates on three triggers: (1) file-system changes via SHChangeNotifyRegister (near-instant), (2) Git index updates detected by polling .git/index timestamp (default 500 ms), and (3) branch switches detected by git rev-parse HEAD comparison on each poll cycle. Default cache mode moves all cache memory to TGitCache.exe, keeping explorer.exe stable. Shell mode retains the cache inside explorer.exe, adding 200–500 MB in a 100k+ file tree. Version-specific behaviors that change the comparison baseline are TortoiseGit 2.14+ (SQLite-backed index), Git for Windows 2.40+ (fsmonitor daemon), Windows 10 20H1+ (SHChangeNotify latency), and TortoiseGit 3.0+ (out-of-process COM surrogate for Shell mode).
The cache uses a two-tier TTL. File-system notifications (SHCNRF_ShellLevel | SHCNRF_InterruptLevel) invalidate affected paths immediately. Index and HEAD polls run at a configurable interval (default 500 ms via undocumented TGitCache.exe.config PollIntervalMs). Aggressive polling (≤200 ms) reduces stale overlays after git add/rm or branch switches but increases CPU and Git process spawns, which can amplify memory fragmentation in the host process. Conservative polling (≥2 s) risks stale overlays until the next poll. Branch switches always invalidate the entire included subtree because HEAD change alters status for all tracked paths; Include/Exclude paths only reduce the monitored directory count at registration time, not the invalidation scope.
Default mode: Recursive cache lives in TGitCache.exe (64-bit). explorer.exe working set stays flat; growth appears in TGitCache.exe private working set. Shell mode: Cache lives in explorer.exe (32-bit on 32-bit shell, 64-bit on 64-bit). Every cached entry (SHITEMID + overlay state) adds to explorer.exe private working set. In large trees this is the primary source of sustained growth. TortoiseGit 3.0+ partially mitigates Shell mode by hosting the overlay handler in a dllhost.exe COM surrogate, but the recursive cache itself remains in-process.
Before comparing cache growth across releases, verify:
git --version) — 2.40+ fsmonitor daemon (core.fsmonitor) can hook into TGitCache, reducing poll frequency.SHChangeNotifyRegister delivery latency, affecting invalidation speed.explorer.exe and TGitCache.exe private working set in Task Manager Details while browsing the tree.TGitCache.exe or explorer.exe CreateFile/ReadFile on .git/index — observe poll interval and invalidation bursts after git checkout.explorer.exe: check Heap and Private Data regions tagged with TortoiseGitShell.dll or TGitCache.dll to confirm allocation source.reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers — entries should show InProcServer32 pointing to TortoiseGitShell64.dll (Shell) or TGitCache.dll (Default surrogate).What TortoiseGit and Git for Windows versions are you running? The answer changes the recommended poll interval and whether fsmonitor can replace polling entirely.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.