use crate::metis::{Cut, DotStore, Dotted, Rhapsody};
use super::super::editor::Replica;
use super::readings::Readings;
fn measured_delta_bytes(delta: &Dotted<Rhapsody>) -> usize {
let context_bytes = delta.context().to_bytes().len();
let store_bytes = delta.store().to_bytes().len();
context_bytes + store_bytes
}
pub(super) fn index_cost_probe(probe_len: usize) -> (usize, usize, usize, usize, usize) {
let mut naive_total = 0usize;
let mut cached_total = 0usize;
let mut naive_last = 0usize;
let mut cached_last = 0usize;
for k in 0..probe_len {
let naive = k + 1;
let cached = 1usize;
naive_total += naive;
cached_total += cached;
naive_last = naive;
cached_last = cached;
}
(
probe_len,
naive_last,
cached_last,
naive_total,
cached_total,
)
}
pub(super) fn assert_c8_index_costs(r: &Readings) {
let (probe_len, naive_last, cached_last, naive_total, cached_total) =
index_cost_probe(r.skeleton_len);
assert!(probe_len > 0, "the probe typed a non-empty chain");
assert_eq!(
naive_last, probe_len,
"naive per-call index rebuild visits the whole skeleton"
);
assert_eq!(
cached_last, 1,
"the maintained index pays one bucket-insert comparison per chain keystroke"
);
assert!(
cached_last < naive_last,
"per-keystroke index work drops with the maintained index"
);
assert!(
cached_total < naive_total,
"cached index maintenance is far below the naive quadratic rebuild total"
);
assert_eq!(
naive_total,
probe_len * (probe_len + 1) / 2,
"naive index-construction total is quadratic in the char count"
);
assert_eq!(
cached_total, probe_len,
"cached index-maintenance total is linear in the char count"
);
}
pub(super) struct FramingProbe {
pub(super) per_keystroke_dots: usize,
pub(super) per_keystroke_bytes: usize,
pub(super) per_keystroke_context_bytes: usize,
pub(super) per_keystroke_floored_context_bytes: usize,
pub(super) batch_dots: usize,
pub(super) batch_bytes: usize,
}
pub(super) fn framing_probe() -> FramingProbe {
let roster = [1u32, 2u32];
let mut writer = Replica::new(1, &roster);
let mut anchor = None;
for _ in 0..100 {
anchor = Some(writer.insert('a', anchor));
}
let prior = writer.text_context().clone();
let peer_cut = Cut::floor_of(&prior);
let _ = writer.insert('z', anchor);
let per_keystroke_delta = writer.text_owed_to(&prior);
let per_keystroke_dots = per_keystroke_delta.store().dots().count();
let per_keystroke_bytes = measured_delta_bytes(&per_keystroke_delta);
let per_keystroke_context_bytes = per_keystroke_delta.context().to_bytes().len();
let per_keystroke_floored = writer.text_owed_since(&peer_cut);
let per_keystroke_floored_context_bytes = per_keystroke_floored.context().to_bytes().len();
let mut batcher = Replica::new(2, &roster);
let prior = batcher.text_context().clone();
let mut anchor = None;
for _ in 0..50 {
anchor = Some(batcher.insert('q', anchor));
}
let batch_delta = batcher.text_owed_to(&prior);
let batch_dots = batch_delta.store().dots().count();
let batch_bytes = measured_delta_bytes(&batch_delta);
FramingProbe {
per_keystroke_dots,
per_keystroke_bytes,
per_keystroke_context_bytes,
per_keystroke_floored_context_bytes,
batch_dots,
batch_bytes,
}
}