Skip to content

Cache catalog composite objects on disk for faster startup#425

Merged
brickbots merged 2 commits into
mainfrom
catalog_cache
May 20, 2026
Merged

Cache catalog composite objects on disk for faster startup#425
brickbots merged 2 commits into
mainfrom
catalog_cache

Conversation

@brickbots
Copy link
Copy Markdown
Owner

Summary

  • Adds a pickle cache for CatalogBuilder's composite-object list at ~/PiFinder_data/cache/catalogs/. Written on first run after the background loader finishes, read on subsequent runs to skip both the SQLite walk and the background loader entirely.
  • Fingerprinted on the source DB's mtime + size plus a CACHE_VERSION constant. logged (user state) is stripped before pickling and re-applied from obs_db on load.
  • Converts ObservationsDatabase.observed_objects_cache from list to set so the per-object check_logged() pass after a cache load is O(n) rather than O(n × m).

Profiling (on the Pi)

Run build() returns Time to fully loaded
Cold (cache miss) 16.2s (priority only) 117.2s
Warm (cache hit) 10.4s (all 151,170 objects) 10.4s

Warm-path breakdown: ~7s pickle.loads (151K dataclass instances), ~1s comet-catalog download, ~1s imports, ~1s grouping/sorting catalogs, ~275ms re-applying logged.

Test plan

  • pytest tests/test_catalog_cache.py — 7 tests pass (round-trip, fingerprint mismatch, corrupt pickle, corrupt meta, logged not persisted, clear, missing-files)
  • Cold + warm end-to-end profile of CatalogBuilder.build() against the real catalogs DB
  • Verify on a fresh device: first run rebuilds cache, second run hits cache, edit source DB → cache invalidates

🤖 Generated with Claude Code

brickbots and others added 2 commits May 19, 2026 18:02
CatalogBuilder rebuilt the full composite-object list from SQLite on every
startup — ~117s of wall time for 151K objects, with ~101s of that hidden
behind the deferred background loader. This adds a pickle-based cache at
~/PiFinder_data/cache/catalogs/, written after the background loader
finishes and read on subsequent startups. The cache is fingerprinted on
the source DB's mtime + size and a CACHE_VERSION constant; user-state
`logged` is reset before pickling and re-applied from obs_db on load. On
cache hit the background loader is skipped entirely.

Also converts ObservationsDatabase.observed_objects_cache from list to
set so the per-object check_logged() pass on cache load runs in O(n)
rather than O(n*m) — drops the re-apply pass from 3.7s to 275ms.

End-to-end startup time on a Pi: 117s -> 10s when the cache is warm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Everything is loaded synchronously inside build() when the cache is warm,
so the UI never sees a "still loading" state and the "Catalogs Fully
Loaded" toast is misleading. Only fire the signal when the background
loader actually completes deferred work (cache-miss path).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@brickbots brickbots merged commit 8839b51 into main May 20, 2026
2 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.

1 participant