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
Stall sentinel counts OS timer deferral of an unfocused window as a main-thread stall #1482
perf/main-thread-stall is raised by the stall sentinel (apps/fluux/src/utils/stallSentinel.ts) when its 500 ms setInterval heartbeat fires more than 1 s late. The only background guard is document.hidden. On macOS, a window that is still visible but unfocused and idle keeps document.hidden === false, yet its timers can be deferred by the OS or WebKit. Those deferrals are recorded as main-thread stalls.
About 95% of the perf/main-thread-stall records share one signature: the latest focus/blur crumb is blur (often minutes old), with no crumb at all in the preceding 10 s and no perf:* crumb. For the 15–21 September builds, this holds for 29 of 29 records. None occurred while focused.
fluux.log has no application activity in the 10 s before 51 of 53 stall lines. There was often nothing for several minutes: no room switch, MAM catch-up or reconnect. The two exceptions are a wake-from-sleep resume.
There was no system sleep in that period, and the display was on at every stall.
For 49 of 53 stalls, RunningBoard shows the app UserInteractiveNonFocal and WindowServer reports the window AppVisible / FUSBProcessWindowState: visible, but without the AppDrawing assertion: the window is on screen and not drawing. The WebContent process stays UserInteractiveFocal.
One continuous run produced about 20 stalls in 3 minutes, up to 7.4 s each, with zero app log lines. It stopped the moment the window regained focus.
Normalised per background hour, the rate varies between builds without tracking code changes: 1.8/h on 8de4642c (Sept 7), 2.9/h on f822a994 (Sept 10), 0–0.8/h on the Sept 15–17 builds, 2.0–4.2/h on the Sept 18–21 builds. The recent increase is within historical variance, and no commit in cc7a7c64..804fd20e adds idle-time work.
The signal therefore mixes real main-thread blocks with OS or WebKit timer deferral of an unfocused, visually idle window, and the second class dominates.
Proposal
Record whether the window had focus when the stall was measured, as a boolean ctx field (no route, no JID).
Add a discriminating heartbeat in a dedicated Worker. If the Worker tick is late too, the process was throttled. If the Worker is on time while the main-thread tick is late, the main thread was genuinely blocked.
Then reclassify or exclude the throttled case, so that perf/main-thread-stall only counts real blocks. Update the docs/ANOMALY_INVARIANTS.md entry: read the latest focus/blur crumb first; blur with no recent crumb points to OS deferral, not app work.
Separate and not covered here: an older class of focused stalls with perf:merge-archive crumbs seen on f822a994.
Activity
feat(anomaly): record whether the window had focus when a stall was m…