From 4eb8eda89db812c3aa40f0226853aa9a20809a92 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 00:49:05 +0100 Subject: soak plumtree links along the way --- src/simtest/bench.rs | 33 +++++++++++++++++++++++++++++---- src/simtest/soak.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) (limited to 'src/simtest') diff --git a/src/simtest/bench.rs b/src/simtest/bench.rs index dac7a48..f8d8123 100644 --- a/src/simtest/bench.rs +++ b/src/simtest/bench.rs @@ -868,14 +868,33 @@ pub(super) fn eager_links( let mut pushes: HashMap> = HashMap::new(); // The round trips of eager and of lazy links, as each node measured them. let (mut eager_rtts, mut lazy_rtts) = (Vec::new(), Vec::new()); + // How many each node holds lazy, and of those how many aren't its neighbours (any + // more); how many neighbours have a round trip fresh enough to count. + let (mut lazy_held, mut lazy_strangers, mut neighbours_timed, mut neighbours_all) = + (0usize, 0usize, 0usize, 0usize); for node in nodes { let Some(lazy) = node.dissemination().lazy() else { return; }; - let (eager, others): (Vec, Vec) = - crate::swarm::topology::our_neighbours(node) - .into_iter() - .partition(|peer| !lazy.contains(peer)); + let neighbours = crate::swarm::topology::our_neighbours(node); + lazy_held += lazy.len(); + lazy_strangers += lazy + .iter() + .filter(|peer| !neighbours.contains(*peer)) + .count(); + { + let rtt = node.lock_rtt(); + let now = tokio::time::Instant::now(); + let fresh = node.timing.rtt_fresh_for(); + neighbours_all += neighbours.len(); + neighbours_timed += neighbours + .iter() + .filter(|peer| rtt.effective(peer, now, fresh).is_some()) + .count(); + } + let (eager, others): (Vec, Vec) = neighbours + .into_iter() + .partition(|peer| !lazy.contains(peer)); { let rtt = node.lock_rtt(); let now = tokio::time::Instant::now(); @@ -937,6 +956,12 @@ pub(super) fn eager_links( eager_rtts.iter().filter(|rtt| **rtt > SLOW_LINK_MS).count(), mean(&lazy_rtts), ); + let _ = writeln!( + out, + " PlumTree's lazy sets: {:.1} held per node, {lazy_strangers} of them not neighbours; \ + {neighbours_timed} of {neighbours_all} neighbours with a fresh round trip", + lazy_held as f64 / count, + ); // From each member, the fastest path to every other along eager links (Dijkstra, // by the net's mean one-way delays), and its hops. let ids: Vec<&String> = pushes.keys().collect(); diff --git a/src/simtest/soak.rs b/src/simtest/soak.rs index 6285e2c..43dfa5d 100644 --- a/src/simtest/soak.rs +++ b/src/simtest/soak.rs @@ -198,6 +198,15 @@ async fn soak_with_churn() { let mut away: Option<(String, Instant)> = None; let (mut joined, mut remade) = (false, false); let mut writes = 0usize; + // PlumTree's links along the way (nothing for another dissemination): once the one + // writer is done, and before the remake; with the PRUNEs and GRAFTs sent until then. + let mut along = String::new(); + let plumtree_sent = |nodes: &[AppState]| -> u64 { + nodes + .iter() + .map(|node| node.traffic.total().sent.plumtree.messages) + .sum() + }; while start.elapsed() < total { let now = Instant::now(); if let Some((id, until)) = &away @@ -225,10 +234,26 @@ async fn soak_with_churn() { next_restart += RESTART_EVERY; } if !joined && start.elapsed() >= CHURN_WORKLOAD { + let mut links = String::new(); + super::bench::eager_links(&mut links, &nodes, &sim.net); + if !links.is_empty() { + along.push_str(&format!( + " after the one writer ({} PRUNE and GRAFT sent):\n{links}", + plumtree_sent(&nodes) + )); + } nodes.push(sim.start_with(&ids[CHURN_NODES - 1], &[genesis], Start::Join, timing)); joined = true; } if !remade && start.elapsed() >= total - CHURN_WORKLOAD / 5 { + let mut links = String::new(); + super::bench::eager_links(&mut links, &nodes, &sim.net); + if !links.is_empty() { + along.push_str(&format!( + " before the remake, writers in turn ({} PRUNE and GRAFT sent):\n{links}", + plumtree_sent(&nodes) + )); + } let (status, report) = crate::remake::testing::start(nodes[0].clone(), json!({ "kind": "compact" }), None) .await; @@ -321,6 +346,13 @@ async fn soak_with_churn() { ); super::bench::sent_kept(&mut out, &nodes).await; neighbour_counts(&mut out, &nodes, "at the end"); + out.push_str(&along); + if !along.is_empty() { + out.push_str(&format!( + " at the end ({} PRUNE and GRAFT sent):\n", + plumtree_sent(&nodes) + )); + } // For PlumTree and HyParView: their links and views at the end (nothing otherwise). super::bench::eager_links(&mut out, &nodes, &sim.net); super::bench::active_views(&mut out, &nodes); -- cgit v1.3.1