use std::{ fs, fmt::Write, hint::black_box, time::{Duration, Instant}, }; fn read_energy_uj() -> u64 { fs::read_to_string("/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj") .map(|s| s.trim().parse().unwrap_or(0)) .unwrap_or_else(|e| { eprintln!("Failed to open energy counter (Are you running with sudo?): {e}"); 0 }) } pub fn bench(name: String, f: fn(&[u8]) -> usize, buffer: &[u8], out: &mut String) { let mut budget: isize = 5_000_000_000; let mut best = Duration::MAX; let mut best_energy = u64::MAX; writeln!(out, " ", name).unwrap(); let res = f(buffer); while budget > 0 { let energy_start = read_energy_uj(); let start = Instant::now(); let res = f(buffer); let elapsed = start.elapsed(); best = best.min(elapsed); best_energy = best_energy.min(read_energy_uj() - energy_start); budget -= elapsed.as_nanos() as isize; black_box(res); } writeln!(out, "\x20 {}\n\ \x20 \n\ \x20 {}", res, best.as_nanos(), (buffer.len() as f64 / (1024.0 * 1024.0)) / best.as_secs_f64(), ).unwrap(); if best_energy != 0 { writeln!(out, "\x20 {}", ((best_energy as f64) / (1000.0 * 1000.0)) / (buffer.len() as f64 / (1024.0 * 1024.0 * 1024.0)), ).unwrap(); } writeln!(out, "\x20 ", ).unwrap(); }