146 lines
4.9 KiB
Rust
146 lines
4.9 KiB
Rust
use rpki::data_model::manifest::ManifestObject;
|
|
use std::hint::black_box;
|
|
use std::path::PathBuf;
|
|
use std::time::Instant;
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct Config {
|
|
sample: Option<String>,
|
|
manifest_path: Option<PathBuf>,
|
|
iterations: u64,
|
|
warmup_iterations: u64,
|
|
repeats: u32,
|
|
}
|
|
|
|
fn usage_and_exit() -> ! {
|
|
eprintln!(
|
|
"Usage:\n ours-manifest-bench (--sample <name> | --manifest <path>) [--iterations N] [--warmup-iterations N] [--repeats N]\n\nExamples:\n cargo run --release -- --sample small-01 --iterations 20000 --warmup-iterations 2000 --repeats 3\n cargo run --release -- --manifest ../../tests/benchmark/selected_der/small-01.mft"
|
|
);
|
|
std::process::exit(2);
|
|
}
|
|
|
|
fn parse_args() -> Config {
|
|
let mut sample: Option<String> = None;
|
|
let mut manifest_path: Option<PathBuf> = None;
|
|
let mut iterations: u64 = 20_000;
|
|
let mut warmup_iterations: u64 = 2_000;
|
|
let mut repeats: u32 = 3;
|
|
|
|
let mut args = std::env::args().skip(1);
|
|
while let Some(arg) = args.next() {
|
|
match arg.as_str() {
|
|
"--sample" => sample = Some(args.next().unwrap_or_else(|| usage_and_exit())),
|
|
"--manifest" => {
|
|
manifest_path = Some(PathBuf::from(args.next().unwrap_or_else(|| usage_and_exit())))
|
|
}
|
|
"--iterations" => {
|
|
iterations = args
|
|
.next()
|
|
.unwrap_or_else(|| usage_and_exit())
|
|
.parse()
|
|
.unwrap_or_else(|_| usage_and_exit())
|
|
}
|
|
"--warmup-iterations" => {
|
|
warmup_iterations = args
|
|
.next()
|
|
.unwrap_or_else(|| usage_and_exit())
|
|
.parse()
|
|
.unwrap_or_else(|_| usage_and_exit())
|
|
}
|
|
"--repeats" => {
|
|
repeats = args
|
|
.next()
|
|
.unwrap_or_else(|| usage_and_exit())
|
|
.parse()
|
|
.unwrap_or_else(|_| usage_and_exit())
|
|
}
|
|
"-h" | "--help" => usage_and_exit(),
|
|
_ => usage_and_exit(),
|
|
}
|
|
}
|
|
|
|
if sample.is_none() && manifest_path.is_none() {
|
|
usage_and_exit();
|
|
}
|
|
if sample.is_some() && manifest_path.is_some() {
|
|
usage_and_exit();
|
|
}
|
|
|
|
Config {
|
|
sample,
|
|
manifest_path,
|
|
iterations,
|
|
warmup_iterations,
|
|
repeats,
|
|
}
|
|
}
|
|
|
|
fn derive_manifest_path(sample: &str) -> PathBuf {
|
|
// Assumes current working directory is `rpki/benchmark/ours_manifest_bench`.
|
|
PathBuf::from(format!("../../tests/benchmark/selected_der/{sample}.mft"))
|
|
}
|
|
|
|
fn main() {
|
|
let cfg = parse_args();
|
|
let manifest_path = cfg
|
|
.manifest_path
|
|
.clone()
|
|
.unwrap_or_else(|| derive_manifest_path(cfg.sample.as_deref().unwrap()));
|
|
|
|
let bytes = std::fs::read(&manifest_path).unwrap_or_else(|e| {
|
|
eprintln!("read manifest fixture failed: {e}; path={}", manifest_path.display());
|
|
std::process::exit(1);
|
|
});
|
|
|
|
let decoded_once = ManifestObject::decode_der(&bytes).unwrap_or_else(|e| {
|
|
eprintln!("decode failed: {e}; path={}", manifest_path.display());
|
|
std::process::exit(1);
|
|
});
|
|
let file_count = decoded_once.manifest.file_count();
|
|
|
|
let mut round_ns_per_op: Vec<f64> = Vec::with_capacity(cfg.repeats as usize);
|
|
let mut round_ops_per_s: Vec<f64> = Vec::with_capacity(cfg.repeats as usize);
|
|
|
|
for _round in 0..cfg.repeats {
|
|
for _ in 0..cfg.warmup_iterations {
|
|
let obj = ManifestObject::decode_der(black_box(&bytes)).expect("warmup decode");
|
|
black_box(obj);
|
|
}
|
|
|
|
let start = Instant::now();
|
|
for _ in 0..cfg.iterations {
|
|
let obj = ManifestObject::decode_der(black_box(&bytes)).expect("timed decode");
|
|
black_box(obj);
|
|
}
|
|
let elapsed = start.elapsed();
|
|
|
|
let ns_per_op = (elapsed.as_secs_f64() * 1e9) / (cfg.iterations as f64);
|
|
let ops_per_s = (cfg.iterations as f64) / elapsed.as_secs_f64();
|
|
round_ns_per_op.push(ns_per_op);
|
|
round_ops_per_s.push(ops_per_s);
|
|
}
|
|
|
|
let avg_ns_per_op = round_ns_per_op.iter().sum::<f64>() / (round_ns_per_op.len() as f64);
|
|
let avg_ops_per_s = round_ops_per_s.iter().sum::<f64>() / (round_ops_per_s.len() as f64);
|
|
|
|
let sample_name = cfg.sample.clone().unwrap_or_else(|| {
|
|
manifest_path
|
|
.file_name()
|
|
.map(|s| s.to_string_lossy().to_string())
|
|
.unwrap_or_else(|| manifest_path.display().to_string())
|
|
});
|
|
let sample_name = sample_name
|
|
.strip_suffix(".mft")
|
|
.unwrap_or(&sample_name)
|
|
.to_string();
|
|
|
|
println!("fixture: {}", manifest_path.display());
|
|
println!();
|
|
println!("| sample | avg ns/op | ops/s | file count |");
|
|
println!("|---|---:|---:|---:|");
|
|
println!(
|
|
"| {} | {:.2} | {:.2} | {} |",
|
|
sample_name, avg_ns_per_op, avg_ops_per_s, file_count
|
|
);
|
|
}
|