use byte_unit::Byte;
use cmd_lib::*;
use rayon::prelude::*;
use std::time::Instant;
use clap::Parser;
const DATA_SIZE: u64 = 10 * 1024 * 1024 * 1024;
#[derive(Parser)]
#[clap(name = "dd_test", about = "Get disk read bandwidth.")]
struct Opt {
#[clap(short, default_value = "4096")]
block_size: u64,
#[clap(short, default_value = "1")]
thread_num: u64,
#[clap(short)]
file: String,
}
#[cmd_lib::main]
fn main() -> CmdResult {
let Opt {
block_size,
thread_num,
file,
} = Opt::parse();
run_cmd! (
info "Dropping caches at first";
sudo bash -c "echo 3 > /proc/sys/vm/drop_caches";
info "Running with thread_num: $thread_num, block_size: $block_size";
)?;
let cnt = DATA_SIZE / thread_num / block_size;
let now = Instant::now();
(0..thread_num).into_par_iter().for_each(|i| {
let off = cnt * i;
let bandwidth = run_fun!(
sudo bash -c "dd if=$file of=/dev/null bs=$block_size skip=$off count=$cnt 2>&1"
| awk r#"/copied/{print $(NF-1) " " $NF}"#
)
.unwrap_or_else(|_| cmd_die!("thread $i failed"));
info!("thread {i} bandwidth: {bandwidth}");
});
let total_bandwidth =
Byte::from_bytes((DATA_SIZE / now.elapsed().as_secs()) as u128).get_appropriate_unit(true);
info!("Total bandwidth: {total_bandwidth}/s");
Ok(())
}