Skip to content

fix(geochron): cache the map per panel size instead of thrashing between two - #283

Open
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/geochron-per-size-map-cache
Open

fix(geochron): cache the map per panel size instead of thrashing between two#283
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/geochron-per-size-map-cache

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

The problem

The rendered map lived in a single _cached_map, and display() re-rendered whenever the cached layout's size differed from the display manager's:

if layout is None or self._cached_map is None \
        or layout["dw"] != dw or layout["dh"] != dh:
    self.update()

Vegas captures this plugin through the display-capture fallback at a narrower width than the panel — 153 px against 512 px on the rig this was found on. So the two sizes alternated, the one-entry cache missed every time, and each switch re-rendered the whole map from scratch. For a capture, that runs on the render thread.

Caught in the act:

15:42:15.016  Fallback: rendering at 153px instead of 512px
15:42:15.016  calling display()
15:42:15.305  display() returned              <- 289ms

Measured across a session at 271, 292, 559, 283, 287 and 639 ms per pass — a visibly stalled marquee.

Where the time goes

Timed the two halves directly:

cost depends on size?
compute_terminator 105 ms no — it's a lat/lon grid
render_map_image ~150 ms yes

So a third of it was recomputing something that didn't depend on the size that had just changed.

The fix

The terminator is computed once per update and shared across sizes. The map is cached per (width, height), and update() re-renders every size in use — on the update worker — so the render thread finds a warm image instead of building one.

Why not just refresh less often

The obvious alternative is to recompute every 30 minutes rather than every 45 seconds. That trades accuracy for the same saving, and it has a sharper edge: _draw_readout() draws a clock. It runs after the map is pasted, on every display() call, so a cached map doesn't freeze the time — but a throttled refresh would put the clock at risk, and the terminator would drift ~7.5° of longitude between rebuilds.

Caching per size costs nothing in accuracy, so the terminator keeps its configured update_interval. The test asserts the readout is still drawn on every display() and still reads the clock fresh, so a later change can't quietly fold it into the cached image.

Verification

Mutation-checked, all four caught:

  • update() refreshing only the live size (the thrash returning)
  • recomputing the terminator per size
  • the render not populating the cache
  • folding the clock into the cached image

Safety harness clean. Deployed to the rig it was diagnosed on; I'll post the before/after render-thread cost here.

…een two

The rendered map lived in a single _cached_map, and display() re-rendered
whenever the cached layout's size differed from the display manager's.

Vegas captures this plugin through the display-capture fallback at a
narrower width than the panel -- 153px against 512px on the rig this was
found on -- so the two sizes alternated and every switch re-rendered from
scratch. For a capture that happens on the render thread. Measured there
at 271ms, 292ms, 559ms, 283ms, 287ms and 639ms per pass, which is a
visibly stalled marquee.

Timed the two halves: compute_terminator is 105ms and does not depend on
size at all, render_map_image is ~150ms and does. The terminator is now
computed once per update and shared, and the map is cached per (width,
height). update() re-renders every size in use, on the update worker, so
the render thread finds a warm image rather than building one.

Deliberately not solved by refreshing less often. The obvious alternative
-- recompute every 30 minutes rather than every 45 seconds -- would trade
accuracy for the same saving, and the readout is drawn after the map on
every display() call, so a throttle risks the clock while a per-size
cache does not. The terminator keeps its configured update_interval.

Mutation-checked, all four caught: update() refreshing only the live size,
recomputing the terminator per size, the render not populating the cache,
and folding the clock into the cached image.

Harness clean.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6b611f6-e949-47bc-86ed-fb8f893d3df6


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 32 complexity

Metric Results
Complexity 32

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

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