use std::sync::{Arc, Mutex};
pub struct Metric {
name: String,
count: usize,
sum: u64,
}
pub struct ScopedMetric<'a> {
metric: Option<&'a mut Metric>,
start: u64,
}
impl<'a> ScopedMetric<'a> {
pub fn new(metric: Option<&'a mut Metric>) -> Self {
let mut v = ScopedMetric { metric, start: 0 };
if v.metric.is_some() {
v.start = high_res_timer();
}
v
}
}
impl<'a> Drop for ScopedMetric<'a> {
fn drop(&mut self) {
if let Some(ref mut metric) = self.metric {
metric.count += 1;
let dt = timer_to_micros(high_res_timer() - self.start);
metric.sum += dt;
}
}
}
pub struct Metrics {
metrics: Vec<Arc<Mutex<Metric>>>,
}
impl Metrics {
pub fn new_metric(&mut self, name: &'static str) -> Arc<Mutex<Metric>> {
let metric = Metric {
name: name.into(),
count: 0,
sum: 0,
};
let metric = Arc::new(Mutex::new(metric));
self.metrics.push(metric.clone());
metric
}
}
pub fn get_time_millis() -> u64 {
timer_to_micros(high_res_timer()) / 1000
}
pub struct Stopwatch {
started: u64,
}
impl Stopwatch {
pub fn new() -> Self {
Stopwatch { started: 0 }
}
pub fn elapsed(&self) -> f64 {
1e-6 * (Self::now() - self.started) as f64
}
pub fn restart(&mut self) {
self.started = Self::now()
}
fn now() -> u64 {
timer_to_micros(high_res_timer())
}
}
#[cfg(not(windows))]
fn high_res_timer() -> u64 {
use std::ptr;
use errno;
use libc;
let mut tv = libc::timeval {
tv_sec: 0,
tv_usec: 0,
};
if unsafe { libc::gettimeofday(&mut tv, ptr::null_mut()) } < 0 {
fatal!("gettimeofday:{}", errno::errno());
}
return tv.tv_sec as u64 * 1000 * 1000 + tv.tv_usec as u64;
}
#[cfg(windows)]
fn high_res_timer() -> u64 {
use winapi;
use kernel32;
use std::mem;
use errno;
let mut counter = unsafe { mem::zeroed::<winapi::LARGE_INTEGER>() };
if 0 == unsafe { kernel32::QueryPerformanceCounter(&mut counter as _) } {
fatal!("QueryPerformanceCounter: {}", errno::errno());
}
counter as u64
}
#[cfg(not(windows))]
fn timer_to_micros(dt: u64) -> u64 {
dt
}
#[cfg(windows)]
fn timer_to_micros(dt: u64) -> u64 {
use std::mem;
use kernel32;
use errno;
use winapi;
lazy_static! {
static ref TICKS_PER_SEC : u64 = {
let mut freq = unsafe { mem::zeroed::<winapi::LARGE_INTEGER>() };
if 0 == unsafe { kernel32::QueryPerformanceFrequency(&mut freq as _)} {
fatal!("QueryPerformanceFrequency: {}", errno::errno());
};
freq as _
};
};
dt * 1000000 / *TICKS_PER_SEC
}