From 13476a8cf598770b501cf0b02a26725a6f5ce3d5 Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 5 Nov 2026 05:46:15 +0100 Subject: trees as member chose --- src/simtest/bench.rs | 10 +++++++++- src/swarm/tree.rs | 25 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/simtest/bench.rs b/src/simtest/bench.rs index 40b413d..39e054e 100644 --- a/src/simtest/bench.rs +++ b/src/simtest/bench.rs @@ -600,7 +600,15 @@ async fn trees(out: &mut String, nodes: &[AppState], net: &crate::transport::sim }; let mut latencies = Vec::new(); for node in nodes { - latencies.extend(crate::swarm::tree::own_latencies(node, &latency).await); + // Each member's parent in this node's tree, as the member chose it. + let mut parents = std::collections::HashMap::new(); + for member in nodes { + if member.local_id() != node.local_id() { + let chosen = crate::swarm::tree::own_parent(member, node.local_id()).await; + parents.insert(member.local_id().to_owned(), chosen); + } + } + latencies.extend(crate::swarm::tree::own_latencies(node, &parents, &latency).await); } let members: usize = latencies.iter().map(|l| l.members).sum(); if members == 0 { diff --git a/src/swarm/tree.rs b/src/swarm/tree.rs index f04e442..29186d8 100644 --- a/src/swarm/tree.rs +++ b/src/swarm/tree.rs @@ -327,7 +327,9 @@ fn shape( /// How long our writes take to reach the members along our own tree, by link latency /// alone (the bench's, which knows each link's): the mean over the members it reaches -/// (and the others do), against two other trees of ours. In one, each member's parent is +/// (and the others do), against two other trees of ours. Our tree as the members chose +/// their parents (`parents`, from `own_parent` on each): of members beyond our +/// neighbours, we don't know the round trips their choice goes by. In one, each member's parent is /// chosen as now, but among those as close to us and as well placed (`rank`) by the /// exact latency, not the round-trip bucket it said; in the other, every member takes the fastest path over the links members /// reach (no tree computed alike everywhere gets below it). In milliseconds, one way. @@ -340,11 +342,23 @@ pub(crate) struct Latencies { pub(crate) fastest: f64, } +/// Our parent in `writer`'s tree, as we choose it (`parent`, by what we and our +/// neighbours said); None if we have none, or no tree is known. +#[cfg(test)] +pub(crate) async fn own_parent(state: &AppState, writer: &str) -> Option { + let (graph, distance) = distances(state, topology::pair_key(writer))?; + let known = known_reaches(state, &graph).await; + let reached = |by: &str, member: &str| known.reached(by, member); + let round_trip = |by: &str, member: &str| known.round_trip(by, member); + parent(&graph, &distance, &reached, &round_trip, state.local_id()).map(str::to_owned) +} + /// `Latencies` of our own tree, by `latency(from, to)` in milliseconds; None while the /// member list isn't known, or we aren't in it, or the tree reaches nobody. #[cfg(test)] pub(crate) async fn own_latencies( state: &AppState, + parents: &HashMap>, latency: &(dyn Fn(&str, &str) -> f64 + Sync), ) -> Option { let me = state.local_id(); @@ -360,10 +374,11 @@ pub(crate) async fn own_latencies( let now: HashMap<&str, Option<&str>> = members .iter() .map(|member| { - ( - *member, - parent(&graph, &distance, &reached, &round_trip, member), - ) + let chosen = match parents.get(*member) { + Some(chosen) => chosen.as_deref(), + None => parent(&graph, &distance, &reached, &round_trip, member), + }; + (*member, chosen) }) .collect(); let faster: HashMap<&str, Option<&str>> = members -- cgit v1.3.1