A person's page (and every face confirmed there) compares each unnamed
face with each of the person's named faces on the UI thread, on one core:
92 000 unnamed faces against 4 100 named ones is some 400 million
512-long dot products, about 2 min 40 s on an Apple M1 Pro with the
window frozen.
- matching::cosine sums in eight lanes, which the compiler vectorizes
(about 4x faster on 512-long embeddings; same result to the last bits).
- matching::person_score: one person's score as rank gives it, with no
names to group by and nothing allocated (same score, tested).
- similar() scores the candidates with rayon: about 3 s in the same case
(benchmark at that scale: 163 s before, 3 s after).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- finish_8bit/finish_deep hand back the render itself when there is no
output sharpening and no watermark. Before, every export cloned the
image (~100 MB at 24 MP) and output_sharpen built a ~290 MB float copy
of it even for SharpenFor::None, all on one thread.
- Output sharpening's box blurs run row-parallel (par_rows); each pixel
is computed as before.
- The parallel JPEG encoder converts each band's rows to YCbCr inside the
band's task instead of first filling whole-image planes (~290 MB for
4:4:4 at 24 MP, written once and read back).
- fdct_quant rounds with plain arithmetic (round_i16) instead of
f32::round, a libm call per coefficient without SSE4.1; it equals
`x.round() as i16` for all 2^32 inputs.
Output is byte-identical (pinned by encoded_bytes_are_pinned and
sharpened_pixels_are_pinned, whose hashes come from main).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
examples/export_bench imports the files given and runs export_photo
(decode, full-size render, encode) N times, forgetting the decoded
original between runs like a batch export does, and prints the median
and minimum wall time. OPT takes export options as app.export JSON,
PHASES=1 times render and encode separately, OUT=dir writes the files
for byte comparisons between builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reuse cached folder listings through Arc and allow tests to inject Local places.
Show browsed folders below hidden ancestors as session roots. Apply the same
hidden-entry checks to folder walks, browsing, import scanning, and Local.
Return an error when either file index is zero. Keep the resolved-path fallback for lenient comparisons. Test both unknown-identity orderings and distinguish identity lookup failures from known-original refusals.
Merge main at 662df66f.