use criterion::{criterion_group, criterion_main, Criterion};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::time::{Duration, Instant};
mod data_source;
#[derive(Copy, Clone, Debug)]
struct BgpReader<'s> {
name: &'s str,
executable: &'s str,
args: &'s [&'s str],
}
const BGP_READERS: &[BgpReader<'static>] = &[
BgpReader {
name: "bgpkit",
executable: "bgpkit-parser",
args: &[],
},
BgpReader {
name: "bgpdump",
executable: "bgpdump",
args: &["-M"],
},
BgpReader {
name: "libparsebgp",
executable: "libparsebgp",
args: &[],
},
BgpReader {
name: "bgpscanner",
executable: "bgpscanner",
args: &[],
},
BgpReader {
name: "Micro BGP Suite",
executable: "bgpgrep",
args: &[],
},
#[cfg(unix)]
BgpReader {
name: "mrt-parser",
executable: "mrt",
args: &["-f"],
},
];
fn perform_run(executable: &PathBuf, args: &[&str], input_file: &PathBuf) -> Duration {
let mut command_setup = Command::new(executable);
command_setup
.args(args)
.arg(input_file)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null());
let start_time = Instant::now();
let status = command_setup.status();
let elapsed = start_time.elapsed();
match status {
Ok(a) if a.success() => {}
Ok(status) => panic!(
"{} exited with failing status code {}",
executable.display(),
status
),
Err(err) => panic!(
"An error occurred while attempting to run {}: {}",
executable.display(),
err
),
}
elapsed
}
fn benchmark(c: &mut Criterion) {
let mut programs_to_test = Vec::new();
for &program in BGP_READERS {
let BgpReader {
name,
executable,
args,
} = program;
let path_result = match executable {
"bgpkit-parser" => Ok(data_source::locate_target_dir().join("release/bgpkit-parser")),
name => which::which(name),
};
match path_result {
Ok(path) => {
println!(
"Benchmarking {} using: {} {} [input file]",
name,
path.display(),
args.join(" ")
);
programs_to_test.push((program, path));
}
Err(err) => {
println!("Unable to locate executable for {name}: {err}");
}
}
}
let update_data = data_source::test_data_file("update-example.gz");
let mut update_group = c.benchmark_group("update-data.gz");
for (program, path) in &programs_to_test {
update_group.bench_function(program.name, |b| {
b.iter_custom(|n| {
let mut total_elapsed = Duration::default();
for _ in 0..n {
total_elapsed += perform_run(path, program.args, &update_data);
}
total_elapsed
})
});
}
update_group.finish();
let rib_data = data_source::test_data_file("rib-example-small.bz2");
let mut rib_group = c.benchmark_group("rib-data.bz2");
rib_group.sample_size(10);
for (program, path) in &programs_to_test {
rib_group.bench_function(program.name, |b| {
b.iter_custom(|n| {
let mut total_elapsed = Duration::default();
for _ in 0..n {
total_elapsed += perform_run(path, program.args, &rib_data);
}
total_elapsed
})
});
}
rib_group.finish();
}
criterion_group!(benches, benchmark);
criterion_main!(benches);