-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathznsappendtest.rs
More file actions
101 lines (83 loc) · 3.04 KB
/
znsappendtest.rs
File metadata and controls
101 lines (83 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use clap::Parser;
use nvme::types::PerformOn;
use std::io::ErrorKind;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
use std::time::Instant;
#[derive(Parser, Debug)]
#[command(author, version, about)]
struct Cli {
#[arg(long)]
device: String,
#[arg(long, default_value_t = 14)]
concurrency: usize,
}
/// Tests throughput for multi-threaded ZNS append
fn main() -> std::io::Result<()> {
let args = Cli::parse();
let _concurrency = args.concurrency.min(14); // clamp to 14
let nvme_config = Arc::new(match nvme::info::nvme_get_info(args.device.as_str()) {
Ok(config) => config,
Err(err) => return Err(err.try_into().unwrap()),
});
let zc = Arc::new(match nvme::info::zns_get_info(&nvme_config) {
Ok(config) => config,
Err(err) => return Err(std::io::Error::new(ErrorKind::Other, err)),
});
nvme::ops::reset_zone(&nvme_config, &zc, PerformOn::AllZones).unwrap();
let write_total = 1077 * 1024 * 1024;
let write_sz = 256 * 1024;
let data: Arc<Vec<u8>> = Arc::new(vec![0; write_total]);
let zones_written = 100;
let zone_counter = Arc::new(AtomicUsize::new(0));
let concurrency = args.concurrency.min(14);
let mut handles = vec![];
let start = Instant::now();
for thread_id in 0..concurrency {
let nvme_config = nvme_config.clone();
let zc = zc.clone();
let data = Arc::clone(&data);
let zone_counter = Arc::clone(&zone_counter);
let handle = thread::spawn(move || {
loop {
let zone = zone_counter.fetch_add(1, Ordering::SeqCst) as u64;
if zone >= zones_written {
break;
}
let mut byte_ind = 0;
while byte_ind < data.len() {
let end = (byte_ind + write_sz).min(data.len());
match nvme::ops::zns_append(&nvme_config, &zc, zone, &data[byte_ind..end]) {
Ok(_) => {}
Err(err) => {
eprintln!(
"Thread {}: Failed at zone {} offset {}: {}",
thread_id, zone, byte_ind, err
);
return Err(std::io::Error::new(ErrorKind::Other, err));
}
}
byte_ind += write_sz;
}
println!("Thread {}: Completed zone {}", thread_id, zone);
}
Ok::<_, std::io::Error>(())
});
handles.push(handle);
}
for handle in handles {
if let Err(e) = handle.join().expect("Thread panicked") {
return Err(e);
}
}
let duration = start.elapsed();
println!("Elapsed: {:.3} seconds", duration.as_secs_f64());
let gib: f64 = (write_total as f64 * zones_written as f64) / (1024.0 * 1024.0 * 1024.0);
println!(
"Wrote {:.3} GiB ({:.3} GiB/s)",
gib,
gib / duration.as_secs_f64()
);
Ok(())
}