You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unbounded concurrent git blame processes pin CPU and freeze the app on large repos (Linux) #368
Installed 0.4.0 Linux build (tryatlas-bin 0.4.0-1, Arch/Omarchy). Opening this repo as the project freezes the app almost instantly: load average 173–332, ~80 processes in D-state, dozens of zombies, tryatlas growing to 4–5.7GB RSS. Had to pkill the app to recover the machine.
Cause
The app spawns unbounded concurrent git blame children. ps during the freeze showed 26+ git processes parented to tryatlas, mostly:
Killing the children doesn't help — they respawn immediately, so it's whack-a-mole until the app itself is killed.
Mechanism
Every open editor tab runs refreshBlame → gitBlameFile (src/features/editor/components/editor-panel.tsx:203-216) backed by the native git_blame_file command. There is no dedup across tabs showing related files, no cancellation when tabs close/switch, and no cap on concurrent git children. Each blame on a large monorepo file is slow, so spawns outpace completions and the storm feeds itself. Restored tabs all fire on launch, which is why it freezes on open rather than degrading gradually.
Repro
Fresh 0.4.0 Linux install, defaults (gitBlameInline defaults true, src-tauri/src/state/atlas_config.rs:506).
Open this repo as the project with a few editors/tabs restored.
Watch ps -eo pid,ppid,args | grep blame and load average.
Confirmation
Setting [settings] gitBlameInline = false in ~/.config/dev.atlas.ide/config.toml and reopening a small folder: 0 git children, CPU back to idle. So the blame path is the whole CPU story.
Expected
One blame per visible file (dedupe across tabs/views of the same file).
Cancel in-flight blame when the view closes or switches file.
Cap concurrent git child processes (or serialize blame through a queue).
Ideally don't blame files until the editor is actually visible/idle, not all restored tabs at launch.
Env
tryatlas-bin 0.4.0-1 (built from 0.4.0 @ e510860), Arch Linux x86-64, 15GB RAM (13GB free at the time — not memory pressure).
I found what keeps this respawning: a feedback loop in the git watcher on Linux. Fix in #375.
notify 8 watches IN_OPEN on Linux, and git_watcher.rs emitted atlas:git-changed for every event, reads included. Every editor tab listens to that event and runs refreshDiffGutter() + refreshBlame() (editor-panel.tsx), and the git store runs status / log / diff HEAD / for-each-ref. Each of those git processes opens .git/HEAD / .git/index / refs, which fires the watcher again 200 ms later, and so on. That's why killing the children didn't help, why the same file got blamed ~20× at once, and why it started the moment restored tabs mounted.
It's visible without any editor tabs open too: on an idle 0.4.0 Linux install with this repo open, Atlas spawns a steady ~6–7 git processes per second, indefinitely. gitBlameInline = false removes the expensive part, but the loop itself keeps running.
#375 ignores read-only events in the watcher, the same rule atlas-theme already applies for the same loop. Real changes (commit, checkout, stage, fetch) still fire it. It references this issue rather than closing it: the hardening asks above (dedupe blame per file, cancel on close, cap concurrent git children) are still worth having on their own.
Activity
ik0zy commentedon Oct 7, 2026
I found what keeps this respawning: a feedback loop in the git watcher on Linux. Fix in #375.
notify8 watchesIN_OPENon Linux, andgit_watcher.rsemittedatlas:git-changedfor every event, reads included. Every editor tab listens to that event and runsrefreshDiffGutter()+refreshBlame()(editor-panel.tsx), and the git store runsstatus/log/diff HEAD/for-each-ref. Each of those git processes opens.git/HEAD/.git/index/ refs, which fires the watcher again 200 ms later, and so on. That's why killing the children didn't help, why the same file got blamed ~20× at once, and why it started the moment restored tabs mounted.It's visible without any editor tabs open too: on an idle 0.4.0 Linux install with this repo open, Atlas spawns a steady ~6–7 git processes per second, indefinitely.
gitBlameInline = falseremoves the expensive part, but the loop itself keeps running.#375 ignores read-only events in the watcher, the same rule
atlas-themealready applies for the same loop. Real changes (commit, checkout, stage, fetch) still fire it. It references this issue rather than closing it: the hardening asks above (dedupe blame per file, cancel on close, cap concurrent git children) are still worth having on their own.fix(git): ignore read events in the git watcher (Linux refresh loop)
fix(git): ignore read events in the git watcher (Linux refresh loop)