feat: add PlanetLab example
Signed-off-by: Stephen Waits <steve@waits.net>
This commit is contained in:
710 files changed
+77116
No files matched your search
@@ -0,0 +1,97 @@
|
||||
// this uses a copy of data from https://github.com/uofa-rzhu3/NetLatency-Data
|
||||
//
|
||||
// for info on the format, see `NetLatency-Data/README.md`
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufReader, Read},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use nanorand::{Rng, WyRand};
|
||||
use vivaldi_nc::NetworkCoordinate;
|
||||
|
||||
// this will return a Vec<Vec<Duration>>
|
||||
fn load_planetlab_file(filename: &str) -> Vec<Vec<Duration>> {
|
||||
// we're expecting 490 lines, each with 490 numbers representing ms
|
||||
let f = File::open(filename).expect("unable to open file");
|
||||
let mut str = String::new();
|
||||
BufReader::new(f)
|
||||
.read_to_string(&mut str)
|
||||
.expect("unable to read file");
|
||||
|
||||
str.lines()
|
||||
.map(|line| {
|
||||
// ...
|
||||
line.split_whitespace()
|
||||
.map(|token| Duration::from_secs_f32(token.parse::<f32>().expect("parse error") / 1000.0))
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
const NUM_LATENCY_SETS: usize = 18;
|
||||
const NUM_NODES: usize = 490;
|
||||
|
||||
fn load_data() -> Vec<Vec<Vec<Duration>>> {
|
||||
// our input filenames (note naming is 1-based, not 0-based)
|
||||
(1..=NUM_LATENCY_SETS)
|
||||
.map(|i| {
|
||||
let filename = format!("examples/NetLatency-Data/PlanetLab/PlanetLabData_{i}");
|
||||
load_planetlab_file(&filename)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// fetch all the PlanetLab latency data
|
||||
let data = load_data();
|
||||
|
||||
// make check to see that we got NUM_NODES worth of data
|
||||
assert_eq!(data.len(), NUM_LATENCY_SETS);
|
||||
assert_eq!(data[0].len(), NUM_NODES);
|
||||
assert_eq!(data[0][0].len(), NUM_NODES);
|
||||
|
||||
// create our network coordinates
|
||||
let mut nc: Vec<NetworkCoordinate<3>> = (0..NUM_NODES)
|
||||
.map(|_| NetworkCoordinate::<3>::new())
|
||||
.collect();
|
||||
|
||||
// the main loop:
|
||||
// 1. choose a local and remote NC
|
||||
// 2. choose one of the 18 latency sample sets
|
||||
// 3. lookup the latency in our data
|
||||
// 4. adjust local NC
|
||||
let mut error = 0.0;
|
||||
for _ in 0..30_000 {
|
||||
let mut rng = WyRand::new();
|
||||
// 1. choose a local and remote NC
|
||||
let i_local = rng.generate::<usize>() % NUM_NODES;
|
||||
let i_remote = rng.generate::<usize>() % NUM_NODES;
|
||||
if i_local == i_remote {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. choose one of the 18 latency sample sets
|
||||
let i_set = 0; //rng.generate::<usize>() % NUM_LATENCY_SETS;
|
||||
|
||||
// 3. lookup the latency in our data
|
||||
let rtt_measured = data[i_set][i_local][i_remote];
|
||||
|
||||
// 4. adjust local NC
|
||||
let nc_remote = nc[i_remote].clone();
|
||||
nc[i_local].update(&nc_remote, rtt_measured);
|
||||
|
||||
// complete, now let's sum up the error
|
||||
error = nc.iter().map(|n| n.error()).sum::<f32>() / NUM_NODES as f32;
|
||||
assert!(error.is_finite());
|
||||
if error < 5.0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert!(error < 5.0);
|
||||
|
||||
// output the NC array as JSON
|
||||
let json = serde_json::to_string_pretty(&nc).expect("JSON serialization error");
|
||||
println!("{json}");
|
||||
}
|
||||
Reference in new issue
Block a user