mirror of
git://git.proxmox.com/git/proxmox-backup.git
synced 2025-01-03 01:18:02 +03:00
examples: add tape write benchmark
A small example that simply writes pseudo-random chunks to a drive. This is useful to benchmark throughput on tape drives. The output and behavior is similar to what the pool writer does, but without writing multiple files, committing or loading data from disk. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
c343c3f7f6
commit
372709326e
91
examples/tape-write-benchmark.rs
Normal file
91
examples/tape-write-benchmark.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use std::{
|
||||
fs::File,
|
||||
io::Read,
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
|
||||
use anyhow::{format_err, Error};
|
||||
use pbs_tape::TapeWrite;
|
||||
use proxmox_backup::tape::drive::{LtoTapeHandle, TapeDriver};
|
||||
|
||||
const URANDOM_PATH: &str = "/dev/urandom";
|
||||
const CHUNK_SIZE: usize = 4 * 1024 * 1024; // 4 MiB
|
||||
const LOG_LIMIT: usize = 4 * 1024 * 1024 * 1024; // 4 GiB
|
||||
|
||||
fn write_chunks<'a>(
|
||||
mut writer: Box<dyn 'a + TapeWrite>,
|
||||
blob_size: usize,
|
||||
max_size: usize,
|
||||
max_time: Duration,
|
||||
) -> Result<(), Error> {
|
||||
// prepare chunks in memory
|
||||
|
||||
let mut blob: Vec<u8> = vec![0u8; blob_size];
|
||||
|
||||
let mut file = File::open(URANDOM_PATH)?;
|
||||
file.read_exact(&mut blob[..])?;
|
||||
|
||||
let start_time = SystemTime::now();
|
||||
loop {
|
||||
let iteration_time = SystemTime::now();
|
||||
let mut count = 0;
|
||||
let mut bytes_written = 0;
|
||||
let mut idx = 0;
|
||||
let mut incr_count = 0;
|
||||
loop {
|
||||
if writer.write_all(&blob)? {
|
||||
eprintln!("LEOM reached");
|
||||
break;
|
||||
}
|
||||
|
||||
// modifying chunks a bit to mitigate compression/deduplication
|
||||
blob[idx] = blob[idx].wrapping_add(1);
|
||||
incr_count += 1;
|
||||
if incr_count >= 256 {
|
||||
incr_count = 0;
|
||||
idx += 1;
|
||||
}
|
||||
count += 1;
|
||||
bytes_written += blob_size;
|
||||
|
||||
if bytes_written > max_size {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let elapsed = iteration_time.elapsed()?.as_secs_f64();
|
||||
let elapsed_total = start_time.elapsed()?;
|
||||
eprintln!(
|
||||
"{:.2}s: wrote {} chunks ({:.2} MB at {:.2} MB/s, average: {:.2} MB/s)",
|
||||
elapsed_total.as_secs_f64(),
|
||||
count,
|
||||
bytes_written as f64 / 1_000_000.0,
|
||||
(bytes_written as f64) / (1_000_000.0 * elapsed),
|
||||
(writer.bytes_written() as f64) / (1_000_000.0 * elapsed_total.as_secs_f64()),
|
||||
);
|
||||
|
||||
if elapsed_total > max_time {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn main() -> Result<(), Error> {
|
||||
let mut args = std::env::args_os();
|
||||
args.next(); // binary name
|
||||
let path = args.next().expect("no path to tape device given");
|
||||
let file = File::open(path).map_err(|err| format_err!("could not open tape device: {err}"))?;
|
||||
let mut drive = LtoTapeHandle::new(file)
|
||||
.map_err(|err| format_err!("error creating drive handle: {err}"))?;
|
||||
write_chunks(
|
||||
drive
|
||||
.write_file()
|
||||
.map_err(|err| format_err!("error starting file write: {err}"))?,
|
||||
CHUNK_SIZE,
|
||||
LOG_LIMIT,
|
||||
Duration::new(60 * 20, 0),
|
||||
)
|
||||
.map_err(|err| format_err!("error writing data to tape: {err}"))?;
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user