Files
2026-09-21 22:29:23 +08:00

70 lines
2.3 KiB
Rust

// Test-only, unprivileged concurrent direct reads and durable DATA writes.
use clap::Parser;
use std::{
fs::{File, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
os::unix::fs::OpenOptionsExt,
path::PathBuf,
sync::{Arc, Barrier},
time::Instant,
};
#[repr(align(16384))]
struct Block([u8; 65536]);
#[derive(Parser)]
#[command(about = "Read eleven cartridge fixtures while writing disposable DATA")]
struct Cli {
#[arg(required = true, num_args = 11)]
paths: Vec<PathBuf>,
}
fn main() {
let paths = Cli::parse().paths;
let barrier = Arc::new(Barrier::new(12));
let origin = Instant::now();
let mut jobs = Vec::new();
for (index, path) in paths.into_iter().enumerate() {
let barrier = barrier.clone();
jobs.push(std::thread::spawn(move || {
let mut file = OpenOptions::new()
.read(true)
.custom_flags(libc::O_DIRECT)
.open(path)
.unwrap(); // O_DIRECT
let mut block = Box::new(Block([0; 65536]));
barrier.wait();
let start = origin.elapsed().as_nanos();
for _ in 0..4 {
file.seek(SeekFrom::Start(0)).unwrap();
for _ in 0..128 {
file.read_exact(&mut block.0).unwrap();
assert!(block.0.iter().all(|b| *b == (index + 2) as u8));
}
}
(
index + 2,
start,
origin.elapsed().as_nanos(),
32 * 1024 * 1024,
)
}));
}
let writer = std::thread::spawn(move || {
let mut file = File::create("/data/stress.bin").unwrap();
let mut block = [0_u8; 65536];
for (i, byte) in block.iter_mut().enumerate() {
*byte = (i % 256) as u8;
}
barrier.wait();
let start = origin.elapsed().as_nanos();
for _ in 0..1024 {
file.write_all(&block).unwrap();
}
file.sync_all().unwrap();
(1, start, origin.elapsed().as_nanos(), 64 * 1024 * 1024)
});
let mut results: Vec<_> = jobs.into_iter().map(|j| j.join().unwrap()).collect();
results.push(writer.join().unwrap());
for (bay, start, end, bytes) in results {
println!("{{\"bay\":{bay},\"start_ns\":{start},\"end_ns\":{end},\"bytes\":{bytes}}}");
}
}