5e8020aa38
Editor previews (colour swatches, arrows, embeds), the 18 obsidian-basics tasks (find and replace with regex, back/forward, auto-pair, footnotes, folding, search operators, split view, PDF/audio/ video embeds, spelling, drag and drop, pinned tabs, settings) and round 2: ```query blocks, stacked tabs, pop-out windows, tasks ticked inside embeds, text around an embed, embeds that follow edits, block menu shortcut. New crates: notescraft-regex (linear-time engine) and notescraft-syntax. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
66 lines
3.2 KiB
Rust
66 lines
3.2 KiB
Rust
//! Open-time measurements for large vaults (run on demand, release build):
|
|
//! `cargo test --release -p notescraft-engine --test perf_open -- --ignored --nocapture`.
|
|
//!
|
|
//! Prints where the time goes when a vault is read: the file list, reading the files, and each
|
|
//! index that is fed with a note. The numbers decide whether an index cache is worth having.
|
|
|
|
mod common;
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
use common::temp_vault;
|
|
use notescraft_engine::Session;
|
|
|
|
const NOTES: usize = 5000;
|
|
const FOLDERS: usize = 50;
|
|
|
|
fn body(n: usize) -> String {
|
|
let next = (n + 1) % NOTES;
|
|
format!(
|
|
"---\ntags: [t{}]\n---\n# Note {n}\n\nParagraph about topic {} and project {} with [[n{next}]] and a #tag{}.\n\n- [ ] task {n}\n- item two\n\n## Section\n\nMore words: alpha beta gamma delta epsilon zeta eta theta iota kappa {n}.\n",
|
|
n % 50,
|
|
n % 97,
|
|
n % 31,
|
|
n % 13
|
|
)
|
|
}
|
|
|
|
fn timed<T>(label: &str, work: impl FnOnce() -> T) -> (T, Duration) {
|
|
let start = Instant::now();
|
|
let out = work();
|
|
let took = start.elapsed();
|
|
println!("{label:<34} {took:>10.2?}");
|
|
(out, took)
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "measurement, run on demand in a release build"]
|
|
fn where_the_time_goes_when_a_vault_is_read() {
|
|
let vault = temp_vault("perf_open");
|
|
for n in 0..NOTES {
|
|
let folder = vault.path().join(format!("f{}", n % FOLDERS));
|
|
std::fs::create_dir_all(&folder).expect("folder");
|
|
std::fs::write(folder.join(format!("n{n}.md")), body(n)).expect("note");
|
|
}
|
|
println!("--- {NOTES} notes in {FOLDERS} folders");
|
|
|
|
let (listing, _) = timed("list the vault (names, sizes)", || notescraft_vault::Vault::open_read_only(vault.path()).and_then(|v| v.list()).expect("list"));
|
|
let paths: Vec<String> = listing.into_iter().filter(|e| !e.is_dir).map(|e| e.path).collect();
|
|
let (texts, _) = timed("read every note", || paths.iter().map(|p| std::fs::read_to_string(vault.path().join(p)).expect("read")).collect::<Vec<_>>());
|
|
let mut links = notescraft_index::Index::new();
|
|
timed("link index: update_note", || paths.iter().zip(&texts).for_each(|(p, t)| links.update_note(p, t).expect("index")));
|
|
let mut search = notescraft_index::search::SearchIndex::new();
|
|
timed("search index: update", || paths.iter().zip(&texts).for_each(|(p, t)| search.update(p, t).expect("search")));
|
|
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))));
|
|
|
|
let (mut session, lazy) = timed("open_lazy (names only)", || Session::open_lazy(vault.path()).expect("lazy"));
|
|
let ((), scan) = timed("index every note in steps", || while !session.index_step(Duration::from_millis(8)).finished {});
|
|
drop(session);
|
|
let (_, eager) = timed("eager open (whole thing)", || Session::open(vault.path()).expect("eager"));
|
|
println!("--- first window after {lazy:.2?}; everything indexed after {scan:.2?} more; eager open {eager:.2?}");
|
|
assert!(lazy < Duration::from_secs(1), "the first window should not wait for the notes: {lazy:?}");
|
|
}
|