Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/znippy-zoomies

lgz/examples/layerbench.rs

//! One measurement per process, so peak RSS is this run's alone:
//!
//! `layerbench <flate2|lgz> <file.gz> <threads> <chunk_bytes> <reps>`
//!
//! Prints one JSON line: best-of-`reps` wall seconds, output MB/s, cores busy
//! (CPU time / wall of the best run) and the process's peak RSS. The output is
//! checked against flate2's on the first rep.

use std::io::Read;
use std::time::Instant;

fn cpu_secs() -> f64 {
    let mut ru: libc::rusage = unsafe { std::mem::zeroed() };
    unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut ru) };
    let t = |v: libc::timeval| v.tv_sec as f64 + v.tv_usec as f64 / 1e6;
    t(ru.ru_utime) + t(ru.ru_stime)
}

fn peak_rss_mb() -> f64 {
    let mut ru: libc::rusage = unsafe { std::mem::zeroed() };
    unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut ru) };
    ru.ru_maxrss as f64 / 1024.0
}

fn flate2(gz: &[u8]) -> Vec<u8> {
    let mut out = Vec::new();
    flate2::read::GzDecoder::new(gz)
        .read_to_end(&mut out)
        .unwrap();
    out
}

fn main() {
    let a: Vec<String> = std::env::args().collect();
    let (how, path) = (&a[1], &a[2]);
    let threads: usize = a[3].parse().unwrap();
    let chunk: usize = a[4].parse().unwrap();
    let reps: usize = a.get(5).map(|s| s.parse().unwrap()).unwrap_or(3);
    let gz = std::fs::read(path).unwrap();
    let (mut best, mut best_cpu, mut out_len, mut segs) = (f64::MAX, 0.0, 0usize, 0usize);
    let mut ok = true;
    for rep in 0..reps {
        let c0 = cpu_secs();
        let t0 = Instant::now();
        let (out, s) = match how.as_str() {
            "flate2" => (flate2(&gz), 1),
            "lgz" => match lgz::bitsplit::decompress(&gz, threads, chunk) {
                Ok((o, st)) => {
                    eprintln!("{st:?}");
                    (o, st.segments)
                }
                Err(e) => {
                    eprintln!("lgz: {e}");
                    (Vec::new(), 0)
                }
            },
            _ => panic!("flate2|lgz"),
        };
        let wall = t0.elapsed().as_secs_f64();
        let cpu = cpu_secs() - c0;
        if rep == 0 && how != "flate2" {
            ok = out == flate2(&gz);
        }
        if wall < best {
            best = wall;
            best_cpu = cpu;
        }
        out_len = out.len();
        segs = s;
        drop(out);
    }
    println!(
        "{{\"how\":\"{how}\",\"file\":\"{}\",\"threads\":{threads},\"chunk_mb\":{},\"in_mb\":{:.1},\"out_mb\":{:.1},\"wall_s\":{best:.3},\"mb_s\":{:.0},\"cores_busy\":{:.2},\"peak_rss_mb\":{:.0},\"segments\":{segs},\"ok\":{ok}}}",
        std::path::Path::new(path)
            .file_name()
            .unwrap()
            .to_string_lossy(),
        chunk >> 20,
        gz.len() as f64 / 1e6,
        out_len as f64 / 1e6,
        out_len as f64 / 1e6 / best,
        best_cpu / best,
        peak_rss_mb(),
    );
}