Time a merge with another device's catalog in catalog_bench

The bench merged the catalog with a copy of itself. Every face in that
merge matches its own box, so the pass never reaches the faces the two
devices disagree about. On the reference library that is 631 of the
tablet's 19,052 faces, and it is the work #77 adds to.

`--remote PEER.sqlite` now also times `merge_remote_catalog` against a
copy of the peer file, and prints the first pass's report so two builds
can be checked for agreement. The first run writes what the peer
brought. The runs after it are the steady state, so compare builds from
two fresh copies of one catalog.
This commit is contained in:
2026-09-26 16:54:05 -04:00
parent 23abfd1827
commit 884b681c21
+30 -2
View File
@@ -1,6 +1,6 @@
//! What the catalog's routine reads cost on a real library, off the GUI.
//!
//! cargo run --release -p dr-catalog --example catalog_bench -- CATALOG.sqlite [FACES_DIR]
//! cargo run --release -p dr-catalog --example catalog_bench -- CATALOG.sqlite [FACES_DIR] [--remote PEER.sqlite]
//!
//! Times `Catalog::open` — which every worker thread pays, including the
//! develop view's fetch of each original and each neighbour it prefetches —
@@ -13,6 +13,13 @@
//! count), whose `library` module is private; their SQL is spelled here as
//! it is spelled there, and has to be kept in step by hand.
//!
//! `--remote` also times a merge with another device's catalog — the
//! server snapshot — which is the pass where the two disagree: faces one
//! side found and the other did not, boxes that moved. The merge with a copy
//! of itself matches every face by its box and never reaches that work. The
//! first of its runs writes what the peer brought; the rest are the steady
//! state, so compare two builds from two fresh copies of one catalog.
//!
//! The figures are for reading side by side before and after a change; they
//! are not a gate. Compare the `cpu` column when the machine is busy. The
//! answers are printed too, so two builds can be checked for agreeing.
@@ -23,7 +30,15 @@ use std::time::{Duration, Instant};
use dr_catalog::{keywords, rating, schema, Catalog};
fn main() {
let args: Vec<String> = std::env::args().skip(1).collect();
let mut args: Vec<String> = std::env::args().skip(1).collect();
let peer = args.iter().position(|a| a == "--remote").map(|at| {
let path = args.get(at + 1).map(PathBuf::from).unwrap_or_else(|| {
eprintln!("--remote needs a catalog");
std::process::exit(2);
});
args.drain(at..at + 2);
path
});
let Some(path) = args.first().map(PathBuf::from) else {
eprintln!("usage: catalog_bench CATALOG.sqlite");
std::process::exit(2);
@@ -117,6 +132,19 @@ fn main() {
let _ = std::fs::remove_file(&scratch);
let _ = std::fs::remove_file(&remote);
if let Some(peer) = &peer {
// A copy, so nothing the merge does to its input reaches the file
// the caller named.
std::fs::copy(peer, &remote).unwrap();
let mut first = None;
time("merge_remote_catalog (--remote)", 5, || {
let report = catalog.merge_remote_catalog(&remote).unwrap();
first.get_or_insert(report);
});
println!(" first pass: {first:?}");
let _ = std::fs::remove_file(&remote);
}
// The face half of a sync pass, against a copy of the face store: both
// directions in the steady state, where nothing is new either way.
if let Some(faces) = args.get(1).map(PathBuf::from) {