//! Benchmarks, as ignored tests (`cargo benchmarks`, `docs/development.md`). //! //! `replay`: carrying writes over into a new epoch's document, last writer wins //! (`delta::replay_newest`): what a rejoin does with the writes made during it, and a //! switch with those made after the remake's base. It finds the paths of every write //! carried, and of every newer change in the new document, by a diff each. use std::time::Instant; use automerge::transaction::Transactable; use automerge::{ObjType, ROOT, ReadDoc, ScalarValue}; use super::delta::{Superseded, replay_newest}; use super::kind::Translator; use crate::document::Document; use crate::document::bench::{document, median}; use crate::document::store; /// `count` changes to `doc`, each writing one key under `data` (from `first` on), made /// at `at` and after. fn writes(doc: &mut Document, first: usize, count: usize, at: i64) { for i in 0..count { let mut transaction = doc.transaction(); let data = transaction .get(ROOT, "data") .expect("read") .map(|(_, id)| id) .unwrap_or_else(|| { transaction .put_object(ROOT, "data", ObjType::Map) .expect("map") }); transaction .put( &data, format!("late{}", first + i), ScalarValue::Int(i as i64), ) .expect("write"); transaction .commit_with(automerge::transaction::CommitOptions::default().with_time(at + i as i64)); } } /// `late` writes made to the old document after `keys` keys, carried into a new one /// holding those keys (as a snapshot, at time 0) and `newer` writes of its own made /// after them. fn replay(keys: usize, late: usize, newer: usize) { let old_base = document(keys); let base = old_base.get_heads(); let mut old = old_base.clone(); writes(&mut old, 0, late, 1_000); let after = old.get_heads(); let mut new = Document::new(); { let mut transaction = new.transaction(); store::materialize_into(&old_base, &mut transaction, &|_| false).expect("snapshot"); transaction.commit_with(automerge::transaction::CommitOptions::default().with_time(0)); } writes(&mut new, late, newer, 2_000); let took = median(5, || { let mut target = new.clone(); let started = Instant::now(); std::hint::black_box(replay_newest( &old, &base, &after, &mut target, &Translator::default(), Superseded::Drop, )); started.elapsed() }); println!( "{:<60} {:>10.3} ms", format!("replay of {late} writes, {keys} keys, {newer} newer changes"), took.as_secs_f64() * 1e3 ); } #[test] #[ignore = "a benchmark: cargo benchmarks"] fn bench_replay() { replay(1_000, 100, 100); replay(100_000, 100, 100); replay(100_000, 1_000, 1_000); }