Files
filmcraft/crates/render/tests/mixer_perf.rs

51 lines
2.3 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Keep the throughput gate in its own executable so parallel correctness tests do not
//! contend for CPU frequency, caches, or memory bandwidth during its timed workload.
//! Cargo runs integration-test executables sequentially; the threshold is unchanged.
use filmcraft_render::{SourceMap, mixer};
#[path = "support/mixer.rs"]
mod support;
use support::{SR, busy_rig};
/// 24 tracks × 3 inserts (EQ, Dynamics, Studio Reverb) + a compressed submix at 48 kHz, one core.
#[test]
// Off Unix there is no per-thread CPU clock (`thread_cpu_secs`), so the timing falls back to wall
// time, which a loaded CI host (Windows runners run the suite in parallel) can push under the
// threshold: genuinely timing-flaky there. On Unix it measures this thread's CPU time and stays on.
#[cfg_attr(not(unix), ignore = "wall-clock timing without a thread CPU clock is load-dependent; run with --ignored")]
fn perf_24_tracks_3_effects_realtime_factor() {
let r = busy_rig(24);
let secs = if cfg!(debug_assertions) { 2.0 } else { 10.0 };
let n = (secs * SR as f64) as usize;
let pool = rayon::ThreadPoolBuilder::new().num_threads(1).build().unwrap();
// warm up (fresh graph + pre-roll), then time steady-state playback-sized blocks
pool.install(|| r.mix_cut(0, 4_800, &[1024], None));
// Thread CPU time, not wall clock: only work done on this one thread matters.
// The separate executable also avoids interference from this crate's correctness tests.
let el = pool.install(|| {
let t0 = thread_cpu_secs();
let w0 = std::time::Instant::now();
r.mix_cut(4_800, n, &[1024], None);
t0.map(|t0| thread_cpu_secs().unwrap_or(t0) - t0).unwrap_or_else(|| w0.elapsed().as_secs_f64())
});
let rt = secs / el;
eprintln!("mixer perf: 24 tracks x 3 inserts + submix, {secs} s of 48 kHz stereo in {el:.3} s of CPU on one core = {rt:.1}x realtime");
let min = if cfg!(debug_assertions) { 1.0 } else { 4.0 };
assert!(rt > min, "realtime factor {rt:.2}");
}
/// CPU seconds used by the calling thread (None where there is no thread clock; callers fall back
/// to wall time).
fn thread_cpu_secs() -> Option<f64> {
#[cfg(unix)]
{
let t = rustix::time::clock_gettime(rustix::time::ClockId::ThreadCPUTime);
Some(t.tv_sec as f64 + t.tv_nsec as f64 * 1e-9)
}
#[cfg(not(unix))]
{
None
}
}