From b0ddfeccbc04a39196717e81daa5dc3aa0f42c69 Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 5 Nov 2026 21:28:47 +0100 Subject: asks by asker --- src/simtest/bench.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) (limited to 'src/simtest') diff --git a/src/simtest/bench.rs b/src/simtest/bench.rs index 08aa365..8368f7d 100644 --- a/src/simtest/bench.rs +++ b/src/simtest/bench.rs @@ -12,6 +12,7 @@ //! long: not taken off, since writes make keepalives unneeded (a pair that exchanges //! anything needs none), so the quiet phase's count isn't part of a workload's. +use std::collections::HashMap; use std::fmt::Write; use std::time::Duration; @@ -300,6 +301,9 @@ struct Totals { /// Per node, by name: its arrivals, their delays summed, and those later than /// `LATE_MS`. by_node: Vec<(String, u64, u64, u64)>, + /// Per node, by name: the changes it asked for that the asked had counted as its + /// (`PeerState::asked_known`), summed over those it asked. + asked_by: HashMap, } /// Arrivals later than this are late (`report`): the propagation buckets above it. @@ -314,7 +318,15 @@ impl Totals { incidents: Incidents::default(), propagation: Propagation::default(), by_node: Vec::new(), + asked_by: HashMap::new(), }; + let names: HashMap = nodes + .iter() + .map(|node| { + let id = node.local_id().to_owned(); + (id.clone(), node.alias.clone().unwrap_or(id)) + }) + .collect(); for node in nodes { let sent = node.traffic.total().sent; for (total, theirs) in counters_mut(&mut totals.sent) @@ -353,8 +365,11 @@ impl Totals { relay.waiting += stats.relay.waiting; relay.off_tree += stats.relay.off_tree; relay.off_tree_ms += stats.relay.off_tree_ms; - for (_, peer_state) in node.peers_snapshot().await { - totals.incidents.add(&peer_state.lock().await.incidents); + for (peer, peer_state) in node.peers_snapshot().await { + let peer_state = peer_state.lock().await; + totals.incidents.add(&peer_state.incidents); + let name = names.get(&peer).cloned().unwrap_or(peer); + *totals.asked_by.entry(name).or_default() += peer_state.asked_known; } let propagation = &mut totals.propagation; for (sum, count) in propagation @@ -860,6 +875,60 @@ fn report( if late.len() > 5 { ", …" } else { "" } ); } + // Who asked for what it was counted as having: the most first, with how many of the + // writes reached it late; and the share of the nodes most writes reached late. + let late_of: HashMap<&str, u64> = late.iter().map(|(name, late, _)| (*name, *late)).collect(); + let mut askers: Vec<(&str, u64)> = during + .1 + .asked_by + .iter() + .map(|(name, asked)| { + let before = during.0.asked_by.get(name).copied().unwrap_or(0); + (name.as_str(), asked - before) + }) + .filter(|(_, asked)| *asked > 0) + .collect(); + askers.sort_by_key(|(name, asked)| (std::cmp::Reverse(*asked), *name)); + let asked: u64 = askers.iter().map(|(_, asked)| asked).sum(); + if asked > 0 { + let listed: Vec = askers + .iter() + .take(5) + .map(|(name, asked)| { + format!( + "{name} {asked} ({} late)", + late_of.get(name).copied().unwrap_or(0) + ) + }) + .collect(); + let writes_seen = |name: &str| { + during + .0 + .by_node + .iter() + .zip(&during.1.by_node) + .find(|((n, ..), _)| n == name) + .map_or(0, |((_, c0, ..), (_, c1, ..))| c1 - c0) + }; + let mostly_late: Vec<&str> = late + .iter() + .filter(|(name, late, _)| 2 * late > writes_seen(name)) + .map(|(name, ..)| *name) + .collect(); + let by_mostly_late: u64 = askers + .iter() + .filter(|(name, _)| mostly_late.contains(name)) + .map(|(_, asked)| asked) + .sum(); + let _ = writeln!( + out, + " asked for, though counted as theirs, by: {}{}; {:.0}% by the {} nodes most writes reached later than {LATE_MS} ms", + listed.join(", "), + if askers.len() > 5 { ", …" } else { "" }, + 100.0 * by_mostly_late as f64 / asked as f64, + mostly_late.len(), + ); + } } /// Values written in `bench_bridge`, unless `BENCH_BRIDGE_WRITES` says otherwise. -- cgit v1.3.1