diff options
| -rw-r--r-- | src/document/bench.rs | 4 | ||||
| -rw-r--r-- | src/document/mod.rs | 2 | ||||
| -rw-r--r-- | src/remake/bench.rs | 89 | ||||
| -rw-r--r-- | src/remake/mod.rs | 2 |
4 files changed, 94 insertions, 3 deletions
diff --git a/src/document/bench.rs b/src/document/bench.rs index 78f87d8..02b530d 100644 --- a/src/document/bench.rs +++ b/src/document/bench.rs @@ -30,7 +30,7 @@ fn sorted(mut heads: Vec<ChangeHash>) -> Vec<ChangeHash> { } /// A document with `keys` keys under `data`, each written by a change of its own. -fn document(keys: usize) -> Document { +pub(crate) fn document(keys: usize) -> Document { let mut doc = Document::new(); let mut map = None; for key in 0..keys { @@ -47,7 +47,7 @@ fn document(keys: usize) -> Document { } /// The median of `runs` timings of `f`. -fn median(runs: usize, mut f: impl FnMut() -> Duration) -> Duration { +pub(crate) fn median(runs: usize, mut f: impl FnMut() -> Duration) -> Duration { let mut times: Vec<Duration> = (0..runs).map(|_| f()).collect(); times.sort_unstable(); times[runs / 2] diff --git a/src/document/mod.rs b/src/document/mod.rs index 4d7fbfe..21050ea 100644 --- a/src/document/mod.rs +++ b/src/document/mod.rs @@ -36,7 +36,7 @@ pub(crate) fn actor(doc: &Document) -> ActorId { pub(crate) mod at; #[cfg(test)] -mod bench; +pub(crate) mod bench; pub(crate) mod changes; pub(crate) mod file; pub(crate) mod lock; diff --git a/src/remake/bench.rs b/src/remake/bench.rs new file mode 100644 index 0000000..213ed4b --- /dev/null +++ b/src/remake/bench.rs @@ -0,0 +1,89 @@ +//! 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); +} diff --git a/src/remake/mod.rs b/src/remake/mod.rs index 25ca7ab..9351cc5 100644 --- a/src/remake/mod.rs +++ b/src/remake/mod.rs @@ -22,6 +22,8 @@ //! depends on `AppState`, peers or sync internals. mod api; +#[cfg(test)] +mod bench; mod catchup; mod content; mod coordinator; |
