Skip to content

perf(blocks): stop rescanning every transcript when no block is found - #569

Merged
sirmalloc merged 3 commits into
sirmalloc:mainfrom
zachthedev:fix-block-metrics-negative-cache
Sep 2, 2026
Merged

perf(blocks): stop rescanning every transcript when no block is found#569
sirmalloc merged 3 commits into
sirmalloc:mainfrom
zachthedev:fix-block-metrics-negative-cache

Conversation

@zachthedev

@zachthedev zachthedev commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

getCachedBlockMetrics writes the cache only when a scan produces metrics. getBlockMetrics() returns
null whenever the newest usage entry is older than the session duration, so nothing is written and the
next repaint repeats the whole scan: a glob over every *.jsonl under the config dir, a statSync on
each, then full reads of everything in the lookback window.

Corpus of 18,837 transcripts, 16.2 GiB, instant shifted so no block is active:

time 16,186 ms
read 1,885 MiB
peak RSS 6.4 GiB
result null, nothing cached

When a block is found: 19,371 ms, then 25 ms, then 0 ms. The positive path already had this; the null
path did not. Replaying 7 days of history at 15-minute intervals, 115 of 673 instants land in it.

This records the empty answer with a 60 s expiry. A new block is reported at most that late, and these
widgets render whole minutes. A positive block still wins; a record naming another config dir is still
ignored. Both helpers are module-private, so the public surface is unchanged.

Five tests. Suppression is asserted by the stored instant not moving, not by spying. Mutation-verified:
never writing the record, never reading it, ignoring expiry, ignoring config dir, letting it beat a live
block, expiry of zero, expiry of a year. All seven fail the suite.

Separate defect from #568, which fixes one transcript being read five times in a single render.
This one is about a scan result that is never cached, so it repeats every repaint. Either can land
alone; they share no file.

getCachedBlockMetrics wrote the cache only when a scan produced metrics.
getBlockMetrics returns null whenever the newest usage entry is older
than the session duration, so nothing was written and the next repaint
repeated the whole scan: a glob over every transcript under the config
directory, a stat on each, then a full read of everything inside the
lookback window.

Measured against a corpus of 18,837 transcripts totalling 16.2 GiB, one
such repaint costs 16,186 ms and 1,885 MiB read, and returns null having
cached nothing. Replaying seven days of real history at fifteen minute
intervals, 115 of 673 instants land in that state, so roughly one
repaint in six paid it.

Record the empty answer with a short expiry and return early while it
stands. A new block is reported at most one interval late, and the
widgets built on this render whole minutes, so a minute of staleness is
not visible. A positive result still takes precedence, and a record
naming a different config directory is still ignored.

The helpers stay module-private; the public surface does not change.
@sirmalloc
sirmalloc merged commit 97606fa into sirmalloc:main Sep 2, 2026
3 checks passed
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.

2 participants