summaryrefslogtreecommitdiff
path: root/benchmarks/harness.rs
blob: c0f90f0e81fc3b2c8add6d4e11b99219db7ab02a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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, "  <benchmark name=\"{}\">", 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   <res>{}</res>\n\
         \x20   <time unit=\"ns\">{}</time>\n\
         \x20   <throughput unit=\"MiB/s\">{}</throughput>",
        res,
        best.as_nanos(),
        (buffer.len() as f64 / (1024.0 * 1024.0)) / best.as_secs_f64(),
    ).unwrap();

    if best_energy != 0 {
        writeln!(out,
            "\x20   <energy-consumption unit=\"J/GiB\">{}</energy-consumption>",
            ((best_energy as f64) / (1000.0 * 1000.0)) / (buffer.len() as f64 / (1024.0 * 1024.0 * 1024.0)),
        ).unwrap();
    }
    writeln!(out,
        "\x20 </benchmark>",
    ).unwrap();

}