Skip to main content

scx_pandemonium/cli/
probe.rs

1use std::sync::atomic::{AtomicBool, Ordering};
2
3static RUNNING: AtomicBool = AtomicBool::new(true);
4
5// PRE-ALLOCATED SAMPLE BUFFER -- NO I/O DURING MEASUREMENT
6const MAX_SAMPLES: usize = 16384;
7
8/// Interactive wakeup probe.
9/// When PANDEMONIUM is running, BPF records latencies to ring buffer.
10/// For EEVDF baseline, we measure in userspace.
11/// Either way: ZERO I/O during measurement, bulk output at end.
12pub fn run_probe() {
13    ctrlc::set_handler(move || {
14        RUNNING.store(false, Ordering::Relaxed);
15    })
16    .ok();
17
18    let mut samples: Vec<i64> = Vec::with_capacity(MAX_SAMPLES);
19
20    let target_ns: i64 = 10_000_000; // 10MS SLEEP TARGET
21    let req = libc::timespec {
22        tv_sec: 0,
23        tv_nsec: target_ns,
24    };
25
26    // HOT LOOP: MEASURE + BUFFER. ZERO I/O.
27    while RUNNING.load(Ordering::Relaxed) && samples.len() < MAX_SAMPLES {
28        let mut t0 = libc::timespec {
29            tv_sec: 0,
30            tv_nsec: 0,
31        };
32        let mut t1 = libc::timespec {
33            tv_sec: 0,
34            tv_nsec: 0,
35        };
36        unsafe {
37            libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut t0);
38            libc::nanosleep(&req, std::ptr::null_mut());
39            libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut t1);
40        }
41        let elapsed_ns = (t1.tv_sec - t0.tv_sec) * 1_000_000_000 + (t1.tv_nsec - t0.tv_nsec);
42        let overshoot_us = (elapsed_ns - target_ns).max(0) / 1000;
43        samples.push(overshoot_us);
44    }
45
46    // BULK OUTPUT AT END -- USE write() DIRECTLY TO MINIMIZE OVERHEAD
47    use std::io::Write;
48    let stdout = std::io::stdout();
49    let mut handle = stdout.lock();
50    for s in &samples {
51        let _ = writeln!(handle, "{}", s);
52    }
53}