Performance improvement#176
Conversation
…riodic orphan GC Hot paths (startup, 3s tick, file watcher, StatusManager background refresh) now use GetStatusFast which runs only git status --porcelain, skipping the two 10s-timeout diff --numstat calls and untracked file line counting. Full status with line stats is reserved for workspace activation and user-initiated sidebar refresh. The sidebar preserves existing line stats when fast-mode updates arrive to prevent flicker. Also adds a 60s periodic tmux orphan GC ticker, session count logging at startup, and temp file cleanup (EXIT trap in openclaw-dx.sh, KEEP_TEMP defaulting to false in openclaw-dogfood.sh with REPORT_DIR cleanup). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 handleProjectsLoaded uses fast git status for active workspace, overwriting full cache entry and losing sidebar line stats
When projects are reloaded (e.g., via state watcher, rescan, or project add/remove) while a workspace is active, handleProjectsLoaded iterates over all workspaces and calls a.requestGitStatus(ws.Root) for each one — including the currently active workspace. Since requestGitStatus now uses fast mode (RefreshFast), this overwrites the active workspace's full-stats cache entry with a fast one (HasLineStats=false).
Root Cause and Impact
At internal/app/app_input_messages_workspace.go:41, the loop calls requestGitStatus(ws.Root) for every workspace:
for i := range a.projects {
for j := range a.projects[i].Workspaces {
ws := &a.projects[i].Workspaces[j]
cmds = append(cmds, a.requestGitStatus(ws.Root))
}
}requestGitStatus now calls RefreshFast (internal/app/app_operations.go:34) which produces a StatusResult with HasLineStats=false. It then calls UpdateCache, overwriting any existing full-stats entry.
When the resulting GitStatusResult message is processed by handleGitStatusResult (internal/app/app_input_messages_workspace.go:336-340), it calls a.sidebar.SetGitStatus(msg.Status) for the active workspace, replacing the sidebar's full status with a fast one.
The sidebar view at internal/ui/sidebar/model_view.go:89 guards with m.gitStatus.HasLineStats, so the +N / -N line stats disappear from the sidebar until either: (1) the cache expires (~5s TTL) and the next 3s tick triggers a full fallback, or (2) a file-watcher event fires a full refresh. This creates a visible ~6-8 second flicker where line stats vanish after any project reload.
Impact: Transient loss of sidebar line stats display whenever projects are reloaded while a workspace is active.
(Refers to line 41)
Prompt for agents
In internal/app/app_input_messages_workspace.go, in the handleProjectsLoaded method, the loop at line 41 calls a.requestGitStatus(ws.Root) for every workspace including the active one. Since requestGitStatus now uses fast mode (no line stats), this overwrites the active workspace's full-stats cache. The fix is to check whether each workspace is the currently active workspace and use requestGitStatusFull for it instead. For example, change the loop body from:
cmds = append(cmds, a.requestGitStatus(ws.Root))
to something like:
if a.activeWorkspace != nil && rootsReferToSameWorkspace(ws.Root, a.activeWorkspace.Root) {
cmds = append(cmds, a.requestGitStatusFull(ws.Root))
} else {
cmds = append(cmds, a.requestGitStatus(ws.Root))
}
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Describe the change and intended behavior.
Quality Checklist
make devchecklocally.make lint-strict-newlocally for changed code.make harness-presets.go test ./internal/tmux ./internal/e2e.