use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Instant;
static CF_OP_COUNT: AtomicU64 = AtomicU64::new(0);
static CF_OP_NANOS: AtomicU64 = AtomicU64::new(0);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct CfOpSnapshot {
pub ops: u64,
pub nanos: u64,
}
pub fn snapshot() -> CfOpSnapshot {
CfOpSnapshot {
ops: CF_OP_COUNT.load(Ordering::Relaxed),
nanos: CF_OP_NANOS.load(Ordering::Relaxed),
}
}
impl CfOpSnapshot {
pub fn ops_since(&self, later: &CfOpSnapshot) -> u64 {
later.ops.saturating_sub(self.ops)
}
pub fn ms_since(&self, later: &CfOpSnapshot) -> f64 {
later.nanos.saturating_sub(self.nanos) as f64 / 1_000_000.0
}
}
pub fn timed<R>(op: impl FnOnce() -> R) -> R {
let start = Instant::now();
let result = op();
CF_OP_COUNT.fetch_add(1, Ordering::Relaxed);
CF_OP_NANOS.fetch_add(start.elapsed().as_nanos() as u64, Ordering::Relaxed);
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn timed_accumulates_count_and_duration() {
let before = snapshot();
timed(|| std::thread::sleep(std::time::Duration::from_millis(5)));
timed(|| ());
let after = snapshot();
assert!(before.ops_since(&after) >= 2);
assert!(before.ms_since(&after) >= 5.0);
}
}