diff options
| author | tv <tv@krebsco.de> | 2026-11-08 19:40:54 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-08 20:42:14 +0100 |
| commit | dff76228f103f36118f19c4492e20cd46f234fb8 (patch) | |
| tree | fda6488786b28d1761787d018d08eaaa796d4f6c /src/document/bench.rs | |
| parent | f61c1ed401aff8feb7a36c92d88500053e9566cf (diff) | |
access: read once what rules read at the same heads
bench_screening shows judging at about 17 µs of a change's 25: some
two and a half reads at its heads (the policy, bans, its node's member
entry, whether there is a registry, the sealed declarations), each
costing as much as working out what the heads cover. Screening judges
most of a batch at the same heads, and those reads are the same for
every change judged there.
Keep them (rules::Reads), by node and by user where they depend on
one, while the heads stay the same; screening keeps one for a batch.
What the heads hold doesn't change as the document takes changes, so
nothing goes stale but by other heads. The benchmark breakdown shows
judging so and afresh.
Diffstat (limited to 'src/document/bench.rs')
| -rw-r--r-- | src/document/bench.rs | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/src/document/bench.rs b/src/document/bench.rs index 026cf7b..2b82036 100644 --- a/src/document/bench.rs +++ b/src/document/bench.rs @@ -684,9 +684,10 @@ fn screening_costs(workload: &str, doc: &Document) { } /// Where screening `changes` spends its time, per change judged: decoding them, their -/// operations placed (`inspect::Inspector`), and judging them (`rules::judge`), of which -/// reading the policy (`policy::of`) and, for scale, one read (the committer's member -/// entry). As screening judges most: the first ones in (the maps they make, which flush +/// operations placed (`inspect::Inspector`), and judging them, as screening does (what +/// is read at the same heads read once, `rules::Reads`) and afresh (`rules::judge`); of +/// that, reading the policy (`policy::of`) and, for scale, one read (the committer's +/// member entry). As screening judges most: the first ones in (the maps they make, which flush /// the batch), the rest judged at the heads after them (`screen`'s frontier). fn screening_parts(changes: &[automerge::Change]) { use crate::access::{policy, rules}; @@ -736,26 +737,28 @@ fn screening_parts(changes: &[automerge::Change]) { .iter() .map(|ops| ops.iter().map(|op| op.path.clone()).collect()) .collect(); - let judge = median(3, || { + let judge_all = |reads: &mut Option<rules::Reads>| { let started = Instant::now(); for (index, change) in rest.iter().enumerate() { - let judged = rules::judge( - &base, - Epoch::GENESIS, - &rules::Change { - hash: change.hash(), - deps: change.deps(), - seen: &seen, - committer: committers[index].as_deref(), - user: None, - paths: &paths[index], - ops: &ops[index], - }, - ); + let change = rules::Change { + hash: change.hash(), + deps: change.deps(), + seen: &seen, + committer: committers[index].as_deref(), + user: None, + paths: &paths[index], + ops: &ops[index], + }; + let judged = match reads { + Some(reads) => rules::judge_reading(&base, Epoch::GENESIS, &change, reads), + None => rules::judge(&base, Epoch::GENESIS, &change), + }; assert_eq!(judged, Ok(()), "every change taken"); } started.elapsed() - }); + }; + let judge = median(3, || judge_all(&mut Some(rules::Reads::default()))); + let afresh = median(3, || judge_all(&mut None)); let read_policy = median(3, || { let started = Instant::now(); for _ in rest { @@ -775,11 +778,12 @@ fn screening_parts(changes: &[automerge::Change]) { }); let per = |d: Duration| d.as_secs_f64() * 1e6 / rest.len().max(1) as f64; println!( - "{:<40} per change: decode {:.2} µs, place {:.2} µs, judge {:.2} µs (policy::of {:.2} µs, one read {:.2} µs)", + "{:<40} per change: decode {:.2} µs, place {:.2} µs, judge {:.2} µs (afresh {:.2} µs: policy::of {:.2} µs, one read {:.2} µs)", "", per(decode), per(place), per(judge), + per(afresh), per(read_policy), per(one_read), ); |
