Skip to content

Commit

Permalink
fix: topology latency
Browse files Browse the repository at this point in the history
  • Loading branch information
will-break-it committed Jan 23, 2025
1 parent 29a4ba1 commit 0a17312
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 97 deletions.
2 changes: 1 addition & 1 deletion crypto-benchmarks.rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "leios_crypto_benchmarks"
version = "0.1.0"
edition = "2024"
edition = "2021"

[dependencies]
blst = "0.3.13"
Expand Down
110 changes: 38 additions & 72 deletions topology-checker/src/analysis/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
pub completion_ratio: f64,
pub min_latency_ms: f64,
pub max_latency_ms: f64,
pub avg_latency_ms: f64,
pub latencies: Vec<f64>, // All latencies for this hop
pub latencies: Vec<f64>,
}

pub fn analyze_hop_stats(topology: &Topology, start_node: &str) -> Vec<HopStats> {
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 &current_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<f64> =
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::<f64>() / 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,
});
}

Expand All @@ -332,7 +313,6 @@ pub fn analyze_hop_stats(topology: &Topology, start_node: &str) -> Vec<HopStats>
}

current_level = next_level;
current_hop += 1;
}

hop_stats
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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);
}
}
25 changes: 1 addition & 24 deletions topology-checker/src/report/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 0a17312

Please sign in to comment.