hashjunkie 0.5.2

Fast multi-algorithm hashing library with file-sharing and cloud hash support
Documentation
use std::env;
use std::fs::File;
use std::io::Read;
use std::time::Instant;

use hashjunkie::{Algorithm, CidProfile, MultiHasher, reset_profile, take_profile};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut args = env::args().skip(1);
    let Some(path) = args.next() else {
        eprintln!("Usage: hashjunkie-cid-profile [cidv0|cidv1] PATH");
        std::process::exit(2);
    };
    let Some(file_path) = args.next() else {
        eprintln!("Usage: hashjunkie-cid-profile [cidv0|cidv1] PATH");
        std::process::exit(2);
    };
    if args.next().is_some() {
        eprintln!("Usage: hashjunkie-cid-profile [cidv0|cidv1] PATH");
        std::process::exit(2);
    }

    let algorithm = match path.as_str() {
        "cidv0" => Algorithm::CidV0,
        "cidv1" => Algorithm::CidV1,
        other => {
            eprintln!("unknown CID version: {other}");
            std::process::exit(2);
        }
    };
    let mut hasher = MultiHasher::new(&[algorithm]);

    let mut file = File::open(&file_path)?;
    let mut buffer = vec![0; 1024 * 1024];
    let mut bytes = 0_u64;

    reset_profile();
    let total_started = Instant::now();
    loop {
        let read = file.read(&mut buffer)?;
        if read == 0 {
            break;
        }
        bytes += read as u64;
        hasher.update(&buffer[..read]);
    }
    let cid = hasher
        .finalize()
        .remove(&algorithm)
        .expect("CID profiler requested one algorithm");
    let total = total_started.elapsed();
    let profile = take_profile();

    println!("file: {file_path}");
    println!("algorithm: {path}");
    println!("bytes: {bytes}");
    println!("cid: {cid}");
    println!("total_ms: {:.3}", total.as_secs_f64() * 1000.0);
    print_profile(profile);

    Ok(())
}

fn print_profile(profile: CidProfile) {
    let measured_ns = profile.chunk_buffering_ns
        + profile.raw_leaf_hashing_ns
        + profile.dag_pb_encoding_ns
        + profile.dag_pb_hashing_ns
        + profile.cid_text_encoding_ns;

    println!();
    println!("{:<24} {:>12} {:>8}", "phase", "ms", "measured");
    print_phase("chunk_buffering", profile.chunk_buffering_ns, measured_ns);
    print_phase("raw_leaf_hashing", profile.raw_leaf_hashing_ns, measured_ns);
    print_phase("dag_pb_encoding", profile.dag_pb_encoding_ns, measured_ns);
    print_phase("dag_pb_hashing", profile.dag_pb_hashing_ns, measured_ns);
    print_phase(
        "cid_text_encoding",
        profile.cid_text_encoding_ns,
        measured_ns,
    );
    print_phase("measured_total", measured_ns, measured_ns);
}

fn print_phase(label: &str, ns: u64, measured_ns: u64) {
    let ms = ns as f64 / 1_000_000.0;
    let pct = if measured_ns == 0 {
        0.0
    } else {
        ns as f64 * 100.0 / measured_ns as f64
    };
    println!("{label:<24} {ms:>12.3} {pct:>7.2}%");
}