From fe6e523443b4dc58f12f53b222a26417d4baafd0 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sat, 26 Sep 2026 13:10:06 -0400 Subject: [PATCH] Count the originals on this device from the cache, not from every image `library::local_original_count` feeds the "On this device" chip and runs beside the rating counts on every star keystroke. On the reference library it cost 1.3-1.4 ms best-of-50 (3 ms on a busy machine) to find 254 originals among 19,000 visible images. It was a correlated EXISTS per visible image: SCAN i USING INDEX images_grid_order SEARCH ic EXISTS USING INTEGER PRIMARY KEY (rowid=?) `image_cache` holds a row only for what has been fetched, so the question is driven from it: `i.id IN (SELECT image_id FROM image_cache WHERE tier_actual >= Original)`, which SQLite plans as the list first and a probe of `images` by id for each entry: SEARCH i USING INTEGER PRIMARY KEY (rowid=?) LIST SUBQUERY 1 SCAN image_cache `image_id` is the cache's primary key, so each image is in the list at most once and the count is the one the EXISTS gave (254). After: 0.05 ms. On a library whose every original is cached this is as much work as before, which is the proportion the rule asks for. The count stays on the keystroke path: dropping it there would leave the chip stale after a background download until something else refreshed it, and at this cost there is nothing left to save. catalog_bench spells the query as dr-ui does, so its copy changes with it. --- core/dr-catalog/examples/catalog_bench.rs | 4 ++-- ui/dr-ui/src/library/spans.rs | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/dr-catalog/examples/catalog_bench.rs b/core/dr-catalog/examples/catalog_bench.rs index f5227f7..3f94f21 100644 --- a/core/dr-catalog/examples/catalog_bench.rs +++ b/core/dr-catalog/examples/catalog_bench.rs @@ -155,8 +155,8 @@ fn local_original_count(conn: &rusqlite::Connection) -> i64 { conn.query_row( "SELECT count(*) FROM images i WHERE i.shadowed_by IS NULL AND i.trashed_at IS NULL - AND EXISTS (SELECT 1 FROM image_cache ic - WHERE ic.image_id = i.id AND ic.tier_actual >= 2)", + AND i.id IN (SELECT ic.image_id FROM image_cache ic + WHERE ic.tier_actual >= 2)", [], |r| r.get(0), ) diff --git a/ui/dr-ui/src/library/spans.rs b/ui/dr-ui/src/library/spans.rs index 08e70df..c6e2aac 100644 --- a/ui/dr-ui/src/library/spans.rs +++ b/ui/dr-ui/src/library/spans.rs @@ -364,13 +364,21 @@ pub(super) fn total_images_filtered( /// Whole-library, like the star counts beside it: the chip says what narrowing /// to it would show, so counting only the current window would make it /// describe the view it exists to change. +/// +/// Driven from `image_cache`, which holds a row only for what has been +/// fetched: an `IN` list the planner walks, probing `images` by id for each. +/// Spelled as a correlated `EXISTS` it walked every visible image and +/// probed the cache for each -- 19,000 probes to find 254 originals on the +/// reference library, 2 ms paid on every star keystroke beside the rating +/// counts. `image_id` is the cache's key, so the list holds each image once +/// and the count is the one the `EXISTS` gave. pub fn local_original_count(catalog: &Catalog) -> Result { let n: i64 = catalog.connection().query_row( &format!( "SELECT count(*) FROM images i WHERE {VISIBLE} - AND EXISTS (SELECT 1 FROM image_cache ic - WHERE ic.image_id = i.id AND ic.tier_actual >= {})", + AND i.id IN (SELECT ic.image_id FROM image_cache ic + WHERE ic.tier_actual >= {})", dr_types::Tier::Original.stored() ), [],