David Venhoff b44a0a5ef3 Execute each benchmark as individual program
- Client now produces one binary per benchmark
2025-09-08 16:35:04 +02:00

85 lines
2.5 KiB
Rust

//! Translated from libnyx/test.c
mod benchmark;
mod benchmark_baseline;
mod benchmark_nyx_pt;
mod nyx;
use crate::benchmark::{Benchmark, ToCsv};
use crate::benchmark_baseline::Baseline;
use clap::Parser;
use std::error::Error;
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
use crate::benchmark_nyx_pt::NyxRunner;
#[derive(Debug, Parser)]
#[command(about = "Tool to execute a program with nyx and trace it with intel pt")]
struct Args {
/// Path to the client binary to execute
client: PathBuf,
/// Directory where the benchmark files get stored
#[arg(short = 'o', long = "output", default_value = "benchmarks")]
output_dir: PathBuf,
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
let nyx_runner = NyxRunner::setup(&args.client)?;
let binary_name = args.client.file_name().unwrap().to_str().unwrap();
benchmark(binary_name, &args.output_dir, nyx_runner)?;
benchmark(binary_name, &args.output_dir, Baseline(&args.client))?;
Ok(())
}
fn benchmark<B: Benchmark>(
binary_name: &str,
output_dir: &Path,
mut benchmark: B,
) -> Result<(), Box<dyn Error>> {
warmup(&mut benchmark);
let results = benchmark_loop(&mut benchmark);
write_results::<B>(binary_name, output_dir, &results)?;
Ok(())
}
/// Warm up to make sure caches are initialized, etc.
fn warmup(benchmark: &mut impl Benchmark) {
let warmup_duration = Duration::from_secs(60);
println!("Warming up for {warmup_duration:?}");
let mut iterations = 0;
let start = Instant::now();
while start.elapsed() < warmup_duration {
benchmark.execute_once();
iterations += 1;
}
println!("Warmed up for {iterations} iterations");
}
fn benchmark_loop<B: Benchmark>(benchmark: &mut B) -> Vec<B::BenchmarkResult> {
let n = 500;
println!("Perform {n} iterations...");
(0..n)
.map(|_| std::hint::black_box(benchmark.execute_once()))
.collect::<Vec<_>>()
}
fn write_results<B: Benchmark>(
binary_name: &str,
output_dir: &Path,
results: &[B::BenchmarkResult],
) -> Result<(), Box<dyn Error>> {
std::fs::create_dir_all(output_dir)?;
let filename = format!("benchmark_{binary_name}_{}", B::TITLE);
let file = std::fs::File::create(output_dir.join(filename))?;
let mut writer = csv::WriterBuilder::new().from_writer(file);
writer.write_record(B::BenchmarkResult::HEADERS)?;
for result in results {
result.write(&mut writer)?;
}
Ok(())
}