mod common;
use std::fs;
use std::io::Write;
use std::time::{Duration, Instant};
use common::{checksum, fixture_bytes, perf_expected_checksum, vector, PERF_FRAMES};
use wav_codec::WavReader;
const MAX_RATIO: f64 = 3.0;
const RUNS: usize = 7;
fn best_of<F: FnMut() -> u64>(mut f: F, expected: u64) -> Duration {
let mut best = Duration::MAX;
for _ in 0..RUNS {
let start = Instant::now();
let got = f();
let took = start.elapsed();
assert_eq!(got, expected, "checksum mismatch");
best = best.min(took);
}
best
}
fn raw_decode(path: &std::path::Path) -> u64 {
let bytes = fs::read(path).unwrap();
let samples: Vec<i16> = bytes[44..]
.chunks_exact(2)
.map(|c| i16::from_le_bytes([c[0], c[1]]))
.collect();
checksum(samples)
}
fn via_iterator(path: &std::path::Path) -> u64 {
let mut reader = WavReader::open(path).unwrap();
let samples: Vec<i16> = reader.samples::<i16>().map(|s| s.unwrap()).collect();
checksum(samples)
}
fn via_read_samples(path: &std::path::Path) -> u64 {
let mut reader = WavReader::open(path).unwrap();
let mut out: Vec<i16> = Vec::with_capacity(reader.len() as usize);
let mut buf = [0i16; 4096];
loop {
let n = reader.read_samples(&mut buf).unwrap();
if n == 0 {
break;
}
out.extend_from_slice(&buf[..n]);
}
checksum(out)
}
#[test]
fn perf_large_read() {
let v = vector("P01");
let bytes = fixture_bytes(&v);
assert_eq!(bytes.len(), 44 + PERF_FRAMES * 4);
let expected = perf_expected_checksum();
let dir = std::env::temp_dir();
let path = dir.join(format!("wav-codec-perf-{}.wav", std::process::id()));
{
let mut f = fs::File::create(&path).unwrap();
f.write_all(&bytes).unwrap();
}
drop(bytes);
let reader = WavReader::open(&path).unwrap();
assert_eq!(reader.len() as usize, PERF_FRAMES * 2);
assert_eq!(reader.duration() as usize, PERF_FRAMES);
drop(reader);
raw_decode(&path);
let raw = best_of(|| raw_decode(&path), expected);
let iter = best_of(|| via_iterator(&path), expected);
let bulk = best_of(|| via_read_samples(&path), expected);
let _ = fs::remove_file(&path);
let raw_s = raw.as_secs_f64().max(1e-9);
let iter_ratio = iter.as_secs_f64() / raw_s;
let bulk_ratio = bulk.as_secs_f64() / raw_s;
let mib = (44.0 + PERF_FRAMES as f64 * 4.0) / (1024.0 * 1024.0);
eprintln!(
"perf_large_read: raw {:.3} ms ({:.0} MiB/s), samples() {:.3} ms ({:.2}x), read_samples {:.3} ms ({:.2}x)",
raw.as_secs_f64() * 1e3,
mib / raw_s,
iter.as_secs_f64() * 1e3,
iter_ratio,
bulk.as_secs_f64() * 1e3,
bulk_ratio
);
assert!(
iter_ratio <= MAX_RATIO,
"samples() is {:.2}x the raw decode, limit {}x",
iter_ratio,
MAX_RATIO
);
assert!(
bulk_ratio <= MAX_RATIO,
"read_samples is {:.2}x the raw decode, limit {}x",
bulk_ratio,
MAX_RATIO
);
}