1806455cd9
Index: .notescraft/cache/index-v1.bin keeps per-note link info, search doc, knowledge passages and lint votes keyed by (mtime, length), re-checked by stat at import; changed notes re-read; corrupt, truncated, oversized or old caches ignored and replaced. The knowledge vocabulary is trusted only by file hash (the old note-count check made a second open slower than a cold one). mdn-docs (14.7k notes, release): second open 1.4 s instead of 15.7-21 s cold. Calendar: a per-session cache of what each note's scan gave the agenda (parsed events, all dated tasks) validated by length and mtime; window switches only filter in memory (mdn-docs 695 ms -> 2.7 ms), the cold pass runs in 8 ms slices across frames while the old grid stays visible, the week review reuses loaded items. Built by Claude Sonnet; verified from a clean checkout of the staged files: 1901 tests in engine, index, knowledge and ui-egui lib plus calendar_view pass, clippy -D warnings on the four crates, xtask layers, tree and i18n clean. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
49 lines
2.1 KiB
Rust
49 lines
2.1 KiB
Rust
//! Calendar window switches on a big vault (run on demand, release build):
|
|
//! `cargo test --release -p notescraft-engine --test perf_calendar -- --ignored --nocapture`.
|
|
//!
|
|
//! The first call is what every call cost before the scan cache; the later ones are window switches.
|
|
|
|
use std::path::PathBuf;
|
|
use std::time::{Duration, Instant};
|
|
|
|
use notescraft_engine::{Session, agenda_items, agenda_items_cached, agenda_restart, agenda_warm};
|
|
|
|
fn day(text: &str) -> notescraft_templates::Date {
|
|
text.parse::<notescraft_calendar::EventTime>().expect("date").date()
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "measurement, run on demand in a release build"]
|
|
fn window_switches_on_a_big_vault() {
|
|
let Some(home) = std::env::var_os("HOME") else { return };
|
|
for name in ["mdn-docs", "k8s-docs", "obsidian-help-all"] {
|
|
let root = PathBuf::from(&home).join("Documents/vaults").join(name);
|
|
if !root.is_dir() {
|
|
continue;
|
|
}
|
|
let Ok(session) = Session::open_read_only(&root) else { continue };
|
|
let timed = |label: &str, work: &dyn Fn() -> usize| {
|
|
let start = Instant::now();
|
|
let items = work();
|
|
println!("{name:<18} {label:<34} {:>10.2?} ({items} items)", start.elapsed());
|
|
};
|
|
let (a, b, c, d) = (day("2026-10-01"), day("2026-10-31"), day("2026-10-19"), day("2026-10-25"));
|
|
timed("first agenda_items (cold)", &|| agenda_items(&session, a, b).0.len());
|
|
timed("second agenda_items, other window", &|| agenda_items(&session, c, d).0.len());
|
|
timed("agenda_items_cached, third window", &|| agenda_items_cached(&session, a, d).0.len());
|
|
agenda_restart(&session);
|
|
let start = Instant::now();
|
|
let (mut frames, mut slowest) = (0, Duration::ZERO);
|
|
loop {
|
|
let frame = Instant::now();
|
|
let done = agenda_warm(&session, Duration::from_millis(8));
|
|
slowest = slowest.max(frame.elapsed());
|
|
frames += 1;
|
|
if done {
|
|
break;
|
|
}
|
|
}
|
|
println!("{name:<18} {:<34} {:>10.2?} ({frames} frames, slowest {slowest:.2?})", "warm pass at 8 ms/frame", start.elapsed());
|
|
}
|
|
}
|