Do not recount face coverage on every confirm, and count it without listing
Every click on the Identity screen's face grid — confirm, reject, split, rename, merge — redrew the whole screen, and the redraw recomputed the coverage line. That line lists every repair's outstanding images to count them: six scans of the images table with a correlated EXISTS over the 8 KB face rows, an ORDER BY the job's visiting order, a Target with its path per row, and a thumbnail-index query per image with faces. On the reference library (24k images, 19k faces) that was ~200 ms of the ~540 ms each click cost, spent computing a figure a confirm cannot change. `refresh` now takes what changed: `Changed::Identities` re-reads the rail and the grid and leaves the coverage line alone; `Changed::Library` — an open, a sweep ending or stopped, the face data deleted — re-reads it too. For the times it does run, `repairs::counts` counts instead of building and dropping the lists, and the thumbnail store is read once (`ThumbStore::held`) rather than probed once per image in the audit, the outstanding list and the proxy repair. `identity_bench` is the measurement: the reads a click performs and the batch writes, timed against a copy of a real catalog.
This commit is contained in:
@@ -240,6 +240,23 @@ impl ThumbStore {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Every file id stored at one size, read from the index in one query.
|
||||
///
|
||||
/// For a pass that asks about thousands of images at once — the face
|
||||
/// audit, the repair lists. Each [`contains`](Self::contains) is a
|
||||
/// prepared statement and a b-tree probe; asked ten thousand times over a
|
||||
/// scan it costs more than the scan does, where one walk of the index is
|
||||
/// a few milliseconds and answers every row.
|
||||
pub fn held(&self, size: ThumbSize) -> Result<std::collections::HashSet<u64>, ThumbError> {
|
||||
let mut stmt = self
|
||||
.index
|
||||
.prepare("SELECT file_id FROM entries WHERE size = ?1")?;
|
||||
let ids = stmt
|
||||
.query_map([size as i64], |r| r.get::<_, i64>(0))?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(ids.into_iter().map(|id| id as u64).collect())
|
||||
}
|
||||
|
||||
/// Store a thumbnail, opening a new shard if the active one is full.
|
||||
///
|
||||
/// Re-storing an existing id overwrites in place rather than migrating it
|
||||
|
||||
Reference in New Issue
Block a user