mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-22 03:33:22 -05:00
The scan asked the disk about every library photo in the folder: is its file there, and has it a sidecar under any of four names. On a network share each question is a round trip, and the scan had just listed the folder. Measured on a hard disk over SMB, for unchanged folders of 1,600 to 2,400 photos: 4.6 to 7.1 s of questions after a listing of 4 to 5 s. - The walk hands each folder's listing over (`walk::files_in_noting`: every entry's name and kind, hidden ones too, and whether that is all of them). The scan walks the folder once, then checks the photos beside the probing of new files. - `sync::Listing` answers "is it there" / "is it a file" where that holds on any file system: a name the folder lists is there; a plain ASCII name is not there when the folder was listed to its end, all its names are ASCII and none is that name in another case. Everything else is asked of the disk as before (a link, a name Windows reads another way, a folder that was not walked, and every name not listed in a folder that holds a name outside ASCII). Now under 0.05 s for those folders. Two things differ on purpose: a file the folder lists is there though it can't be opened by its path (a folder that may be listed but not searched, an over-long path), where such photos were listed as missing; and the answers are the folder as the walk saw it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
48 lines
1.9 KiB
Rust
48 lines
1.9 KiB
Rust
//! What a Synchronize Folder scan costs on a folder whose photos are all in the library and
|
|
//! unchanged: the walk, and the check of every photo and its sidecar. Reads the folder; writes
|
|
//! nothing there, and probes no file (the library is made from the folder's own listing).
|
|
//!
|
|
//! `cargo run --release -p lightcraft-engine --example sync_scan_bench -- <folder>`
|
|
use std::time::Instant;
|
|
|
|
use lightcraft_catalog::{Op, Photo, Source};
|
|
use lightcraft_engine::Session;
|
|
use lightcraft_engine::sync::{SyncInput, SyncProgress, scan_with};
|
|
|
|
fn main() {
|
|
let Some(folder) = std::env::args().nth(1) else {
|
|
eprintln!("usage: sync_scan_bench <folder>");
|
|
return;
|
|
};
|
|
let mut s = Session::new();
|
|
let t = Instant::now();
|
|
let files = lightcraft_engine::import::expand(std::slice::from_ref(&folder), None);
|
|
println!("{} files listed in {:.1} s (the library is made of them)", files.len(), t.elapsed().as_secs_f64());
|
|
for f in &files {
|
|
let id = s.catalog.alloc_photo_id();
|
|
let name = std::path::Path::new(f).file_name().map(|n| n.to_string_lossy().to_string()).unwrap_or_default();
|
|
let p = Photo::new(id, Source::File { path: f.clone() }, &name, "JPEG", 6, 4, "2026-01-01T00:00:00");
|
|
if s.catalog.apply(Op::AddPhoto { photo: Box::new(p) }).is_err() {
|
|
eprintln!("could not add {name}");
|
|
}
|
|
}
|
|
for run in 0..2 {
|
|
let input = match SyncInput::new(&mut s, &folder, true) {
|
|
Ok(input) => input,
|
|
Err(e) => {
|
|
eprintln!("{e}");
|
|
return;
|
|
}
|
|
};
|
|
let t = Instant::now();
|
|
let changes = scan_with(input, &SyncProgress::default());
|
|
println!(
|
|
"run {run}: scan {:.1} s ({} new, {} missing, {} with sidecar news)",
|
|
t.elapsed().as_secs_f64(),
|
|
changes.new.len(),
|
|
changes.missing.len(),
|
|
changes.metadata.len()
|
|
);
|
|
}
|
|
}
|