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>
60 lines
2.9 KiB
Rust
60 lines
2.9 KiB
Rust
//! Open-time measurement on a real vault (run on demand, release build):
|
|
//! `cargo test --release -p notescraft-engine --test perf_open_cache -- --ignored --nocapture`.
|
|
//!
|
|
//! Skipped when `~/Documents/vaults/mdn-docs` is missing. Prints per-stage totals of what
|
|
//! `Session::index_note` does, then the whole open (cold, then from the index cache).
|
|
|
|
use std::path::PathBuf;
|
|
use std::time::{Duration, Instant};
|
|
|
|
use notescraft_engine::Session;
|
|
|
|
fn timed<T>(label: &str, work: impl FnOnce() -> T) -> T {
|
|
let start = Instant::now();
|
|
let out = work();
|
|
println!("{label:<34} {:>10.2?}", start.elapsed());
|
|
out
|
|
}
|
|
|
|
fn open_all(root: &std::path::Path) -> Session {
|
|
let mut session = Session::open_lazy(root).expect("lazy");
|
|
while !session.index_step(Duration::MAX).finished {}
|
|
session
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "measurement, run on demand in a release build"]
|
|
fn cold_and_cached_open_of_a_real_vault() {
|
|
let Some(home) = std::env::var_os("HOME") else { return };
|
|
let root = PathBuf::from(home).join("Documents/vaults/mdn-docs");
|
|
if !root.is_dir() {
|
|
return;
|
|
}
|
|
let listing = notescraft_vault::Vault::open_read_only(&root).and_then(|v| v.list()).expect("list");
|
|
let paths: Vec<String> = listing.into_iter().filter(|e| !e.is_dir && e.path.to_ascii_lowercase().ends_with(".md")).map(|e| e.path).collect();
|
|
println!("--- {} notes", paths.len());
|
|
let texts = timed("read every note", || paths.iter().filter_map(|p| std::fs::read_to_string(root.join(p)).ok()).collect::<Vec<_>>());
|
|
let mut links = notescraft_index::Index::new();
|
|
timed("link index: update_note", || paths.iter().zip(&texts).for_each(|(p, t)| drop(links.update_note(p, t))));
|
|
let mut search = notescraft_index::search::SearchIndex::new();
|
|
timed("search index: update", || paths.iter().zip(&texts).for_each(|(p, t)| drop(search.update(p, t))));
|
|
let mut passages = notescraft_knowledge::Index::default();
|
|
timed("knowledge passages: update", || paths.iter().zip(&texts).for_each(|(p, t)| drop(passages.update(p, t))));
|
|
let mut vocab = notescraft_knowledge::Vocab::default();
|
|
timed("knowledge vocabulary: update", || paths.iter().zip(&texts).for_each(|(p, t)| drop(vocab.update(p, t))));
|
|
drop((links, search, passages, vocab, texts));
|
|
|
|
let _ = std::fs::remove_dir_all(root.join(".notescraft/cache"));
|
|
let _ = std::fs::remove_file(root.join(".notescraft/knowledge-vocab.json"));
|
|
let lazy = timed("open_lazy (names only)", || Session::open_lazy(&root).expect("lazy"));
|
|
drop(lazy);
|
|
let cold = timed("cold open + index everything", || open_all(&root));
|
|
drop(cold);
|
|
let size = std::fs::metadata(root.join(".notescraft/cache/index-v1.bin")).map_or(0, |meta| meta.len());
|
|
println!("cache file: {} MiB", size / (1024 * 1024));
|
|
let lazy = timed("open_lazy with a cache", || Session::open_lazy(&root).expect("lazy"));
|
|
drop(lazy);
|
|
let cached = timed("cached open + index everything", || open_all(&root));
|
|
drop(cached);
|
|
}
|