Skip to content

perf(tui): throttle budget/anomaly rollups off per-event path (0.1.2)#32

Merged
mishanefedov merged 4 commits into
mainfrom
perf-tui-rollup-throttle
May 25, 2026
Merged

perf(tui): throttle budget/anomaly rollups off per-event path (0.1.2)#32
mishanefedov merged 4 commits into
mainfrom
perf-tui-rollup-throttle

Conversation

@mishanefedov
Copy link
Copy Markdown
Owner

Summary

  • The TUI recomputed budgetStatus (up to 50k SQLite rows) and anomalies (5k) on every event (useMemo keyed on state.events).
  • On a ~1GB DB a single budget query is ~1.08s — running it per event during backfill pegged the shared event loop, freezing the TUI (q unresponsive) and starving the in-process web server opened with w (minutes to load).
  • Fix: recompute the store-backed rollups on a ~2.5s interval tick, not per event. Live timeline still updates instantly; no-store path unchanged.
  • Bumps to 0.1.2 + CHANGELOG.

Test plan

  • npm run typecheck clean
  • npm test — 404 passed
  • npm run build OK
  • Quantified: single 50k budget query = 1078ms on a 1GB DB (was per-event; now ~1/2.5s)

…1.2)

The TUI recomputed budgetStatus (up to 50k store rows) and anomalies (5k)
on every event via a useMemo keyed on state.events. On a ~1GB DB a single
budget query is ~1.08s; running it per event during backfill pegged the
shared event loop — freezing the TUI (q unresponsive) and starving the
in-process web server opened with 'w'.

Recompute the store-backed rollups on a 2.5s interval tick instead of per
event; the live timeline still updates instantly. No-store path unchanged.
The per-file backfill re-read the last 512KB of EVERY session file on
startup (826 Claude files + 1.2GB OpenClaw on a heavy install), blocking
the event loop ~8-10s — which froze the TUI and starved the in-process
web server (press 'w').

Stale files (mtime older than 48h) now tail from EOF instead; their
history is already in the SQLite store the timeline seeds from. Recently
modified files still backfill the gap since the last run.

Shared helper backfillStartOffset() in util/backfill.ts, used by the
claude-code, openclaw, and codex adapters.

Smoke (1GB history): in-process web during startup 19s -> ~1s -> 0.34s.
Addresses Codex [P2]: skipping stale (>48h) files' backfill caused data
loss on first run / empty / unavailable / freshly-pruned store — those
files were never ingested, so their events were dropped (the store seed
only helps after a prior successful ingestion).

Now the stale-skip is enabled only when the store seed returns >0 events
(setStaleSkipEnabled in util/backfill.ts, called from both the serve and
TUI startup paths). Fresh/empty store -> full backfill (one-time, complete);
returning users -> fast skip. Default off keeps adapter unit tests intact.
Two remaining loop-blockers eliminated so the TUI + in-process web stay
responsive throughout startup, not just after it settles:

1. Adapter initial-scan backfill now drains one file per macrotask
   (util/backfill-queue.ts) instead of a synchronous file-read storm, so
   HTTP/SSE interleave during startup. Live post-scan events still inline.

2. Budget rollup aggregates in SQL (store.budgetRollup: SUM today's cost +
   top session by total) — ~20ms vs ~1s pulling 50k rows into JS every
   2.5s tick. Breach logic shared via budgets.budgetStatusFromTotals so
   in-memory and SQL paths can't diverge.

Smoke (1GB history): sub-100ms steady-state; web usable in ~3s (was minutes).
@mishanefedov mishanefedov merged commit 4fff2ef into main May 25, 2026
3 checks passed
@mishanefedov mishanefedov deleted the perf-tui-rollup-throttle branch May 25, 2026 23:33
mishanefedov added a commit that referenced this pull request May 25, 2026
perf(tui): throttle budget/anomaly rollups off per-event path (0.1.2)
mishanefedov added a commit that referenced this pull request May 25, 2026
perf(tui): throttle budget/anomaly rollups off per-event path (0.1.2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant