From 0a17312f86ac1304aff6f0f731f3740871fd96eb Mon Sep 17 00:00:00 2001 From: William Wolff Date: Thu, 23 Jan 2025 19:59:50 +0000 Subject: [PATCH] fix: topology latency --- crypto-benchmarks.rs/Cargo.toml | 2 +- topology-checker/src/analysis/basic.rs | 110 +++++++++---------------- topology-checker/src/report/mod.rs | 25 +----- 3 files changed, 40 insertions(+), 97 deletions(-) diff --git a/crypto-benchmarks.rs/Cargo.toml b/crypto-benchmarks.rs/Cargo.toml index b62ee1b6..6c1adb18 100644 --- a/crypto-benchmarks.rs/Cargo.toml +++ b/crypto-benchmarks.rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "leios_crypto_benchmarks" version = "0.1.0" -edition = "2024" +edition = "2021" [dependencies] blst = "0.3.13" diff --git a/topology-checker/src/analysis/basic.rs b/topology-checker/src/analysis/basic.rs index 464924ea..7f79ec93 100644 --- a/topology-checker/src/analysis/basic.rs +++ b/topology-checker/src/analysis/basic.rs @@ -263,67 +263,48 @@ pub fn analyze_network_stats(topology: &Topology) -> NetworkStats { #[derive(Debug)] pub struct HopStats { pub hop_number: usize, - pub nodes_reached: Vec, - pub completion_ratio: f64, - pub min_latency_ms: f64, - pub max_latency_ms: f64, - pub avg_latency_ms: f64, - pub latencies: Vec, // All latencies for this hop + pub latencies: Vec, } pub fn analyze_hop_stats(topology: &Topology, start_node: &str) -> Vec { let mut hop_stats = Vec::new(); - let total_nodes = topology.nodes.len(); - - // Track visited nodes and their distances/latencies from start - let mut visited = HashMap::new(); - let mut latencies = HashMap::new(); - let mut current_hop = 0; - let mut processed_nodes = HashSet::new(); + let mut visited = HashSet::new(); // Initialize with start node let mut current_level = vec![start_node.to_string()]; - visited.insert(start_node.to_string(), 0); - latencies.insert(start_node.to_string(), 0.0); + visited.insert(start_node.to_string()); + + // Add hop 0 with just the start node (0 latency) + hop_stats.push(HopStats { + hop_number: 0, + latencies: vec![0.0], + }); + let mut current_hop = 0; while !current_level.is_empty() { let mut next_level = Vec::new(); + let mut current_hop_latencies = Vec::new(); - // Process all nodes at current hop level + // Find all unvisited neighbors of current level nodes for node in ¤t_level { - processed_nodes.insert(node.clone()); if let Some(node_data) = topology.nodes.get(node) { - // Check all neighbors for (neighbor, producer) in &node_data.producers { - if !visited.contains_key(neighbor) { - visited.insert(neighbor.clone(), current_hop + 1); - let total_latency = latencies[node] + producer.latency_ms; - latencies.insert(neighbor.clone(), total_latency); + if !visited.contains(neighbor) { + visited.insert(neighbor.clone()); + // Store only the direct latency between these nodes + current_hop_latencies.push(producer.latency_ms); next_level.push(neighbor.clone()); } } } } - // Create stats for current hop level - let nodes_at_hop = current_level; - if !nodes_at_hop.is_empty() { - let mut latencies_at_hop: Vec = - nodes_at_hop.iter().map(|n| latencies[n]).collect(); - latencies_at_hop.sort_by(|a, b| a.total_cmp(b)); - - let min_latency = *latencies_at_hop.first().unwrap_or(&f64::INFINITY); - let max_latency = *latencies_at_hop.last().unwrap_or(&0.0); - let avg_latency = latencies_at_hop.iter().sum::() / latencies_at_hop.len() as f64; - + // If we found any new nodes, add their latencies as a new hop + if !current_hop_latencies.is_empty() { + current_hop += 1; hop_stats.push(HopStats { hop_number: current_hop, - nodes_reached: nodes_at_hop, - completion_ratio: processed_nodes.len() as f64 / total_nodes as f64, - min_latency_ms: min_latency, - max_latency_ms: max_latency, - avg_latency_ms: avg_latency, - latencies: latencies_at_hop, + latencies: current_hop_latencies, }); } @@ -332,7 +313,6 @@ pub fn analyze_hop_stats(topology: &Topology, start_node: &str) -> Vec } current_level = next_level; - current_hop += 1; } hop_stats @@ -489,33 +469,21 @@ mod tests { // Check hop 0 let hop0 = &hop_stats[0]; assert_eq!(hop0.hop_number, 0); - assert_eq!(hop0.nodes_reached.len(), 1); - assert!(hop0.nodes_reached.contains(&"node1".to_string())); - assert_eq!(hop0.completion_ratio, 0.25); // 1/4 nodes - assert_eq!(hop0.min_latency_ms, 0.0); - assert_eq!(hop0.max_latency_ms, 0.0); - assert_eq!(hop0.avg_latency_ms, 0.0); + assert_eq!(hop0.latencies.len(), 1); + assert_eq!(hop0.latencies[0], 0.0); // Check hop 1 let hop1 = &hop_stats[1]; assert_eq!(hop1.hop_number, 1); - assert_eq!(hop1.nodes_reached.len(), 2); - assert!(hop1.nodes_reached.contains(&"node2".to_string())); - assert!(hop1.nodes_reached.contains(&"node3".to_string())); - assert_eq!(hop1.completion_ratio, 0.75); // 3/4 nodes - assert_eq!(hop1.min_latency_ms, 10.0); // node1->node2 latency - assert_eq!(hop1.max_latency_ms, 20.0); // node1->node3 latency - assert_eq!(hop1.avg_latency_ms, 15.0); // (10 + 20) / 2 + assert_eq!(hop1.latencies.len(), 2); + assert_eq!(hop1.latencies[0], 10.0); + assert_eq!(hop1.latencies[1], 20.0); // Check hop 2 let hop2 = &hop_stats[2]; assert_eq!(hop2.hop_number, 2); - assert_eq!(hop2.nodes_reached.len(), 1); - assert!(hop2.nodes_reached.contains(&"node4".to_string())); - assert_eq!(hop2.completion_ratio, 1.0); // 4/4 nodes - assert_eq!(hop2.min_latency_ms, 35.0); // node1->node3->node4 latency - assert_eq!(hop2.max_latency_ms, 35.0); - assert_eq!(hop2.avg_latency_ms, 35.0); + assert_eq!(hop2.latencies.len(), 1); + assert_eq!(hop2.latencies[0], 35.0); } #[test] @@ -554,11 +522,8 @@ mod tests { assert_eq!(hop_stats.len(), 1); let hop0 = &hop_stats[0]; assert_eq!(hop0.hop_number, 0); - assert_eq!(hop0.nodes_reached.len(), 1); - assert_eq!(hop0.completion_ratio, 0.5); // 1/2 nodes - assert_eq!(hop0.min_latency_ms, 0.0); - assert_eq!(hop0.max_latency_ms, 0.0); - assert_eq!(hop0.avg_latency_ms, 0.0); + assert_eq!(hop0.latencies.len(), 1); + assert_eq!(hop0.latencies[0], 0.0); } #[test] @@ -637,19 +602,20 @@ mod tests { // Check hop 0 let hop0 = &hop_stats[0]; - assert_eq!(hop0.nodes_reached.len(), 1); - assert_eq!(hop0.completion_ratio, 1.0 / 3.0); + assert_eq!(hop0.hop_number, 0); + assert_eq!(hop0.latencies.len(), 1); + assert_eq!(hop0.latencies[0], 0.0); // Check hop 1 let hop1 = &hop_stats[1]; - assert_eq!(hop1.nodes_reached.len(), 1); - assert_eq!(hop1.completion_ratio, 2.0 / 3.0); - assert_eq!(hop1.min_latency_ms, 10.0); + assert_eq!(hop1.hop_number, 1); + assert_eq!(hop1.latencies.len(), 1); + assert_eq!(hop1.latencies[0], 10.0); // Check hop 2 let hop2 = &hop_stats[2]; - assert_eq!(hop2.nodes_reached.len(), 1); - assert_eq!(hop2.completion_ratio, 1.0); - assert_eq!(hop2.min_latency_ms, 30.0); + assert_eq!(hop2.hop_number, 2); + assert_eq!(hop2.latencies.len(), 1); + assert_eq!(hop2.latencies[0], 30.0); } } diff --git a/topology-checker/src/report/mod.rs b/topology-checker/src/report/mod.rs index 770eb08e..9a8fe682 100644 --- a/topology-checker/src/report/mod.rs +++ b/topology-checker/src/report/mod.rs @@ -139,30 +139,7 @@ pub fn generate_report(topology: &Topology, filename: &str, start_node: Option<& if let Some(node) = start_node { let hop_stats = analyze_hop_stats(topology, node); - report.push_str("\n## Hop-by-Hop Analysis\n\n"); - report.push_str(&format!("Starting from node: {}\n\n", node)); - report.push_str( - "| Hop | Nodes Reached | Completion | Min Latency | Avg Latency | Max Latency |\n", - ); - report.push_str( - "|-----|---------------|------------|-------------|-------------|-------------|\n", - ); - - for stats in &hop_stats { - report.push_str(&format!( - "| {} | {} | {:.1}% | {:.2} ms | {:.2} ms | {:.2} ms |\n", - stats.hop_number, - stats.nodes_reached.len(), - stats.completion_ratio * 100.0, - stats.min_latency_ms, - stats.avg_latency_ms, - stats.max_latency_ms - )); - } - report.push_str("\n"); - - // Add raw latencies for each hop - report.push_str("### Raw Latencies per Hop\n\n"); + report.push_str("\n### Raw Latencies per Hop\n\n"); for stats in &hop_stats { report.push_str(&format!("Hop {}: CDF[", stats.hop_number)); let scale = 1.0 / stats.latencies.len() as f64;