- Cargo workspace (core, plugins, tui, cli) with drop-in compatible CLI - Python-compatible config file handling, limits, views, rates, MMM, history - process collection via sysinfo + procfs, filters, thresholds, events, actions - 20 core plugins (cpu, percpu, mem, memswap, load, fs, network, diskio, ...) - stdout, stdout-csv, stdout-json, --issue, --modules-list output modes - differential test harness against the Python implementation
114 lines
2.6 KiB
Rust
114 lines
2.6 KiB
Rust
//! Simple timers and the global "time since last update" registry.
|
|
|
|
use std::collections::HashMap;
|
|
use std::sync::Mutex;
|
|
use std::sync::OnceLock;
|
|
use std::time::Instant;
|
|
|
|
/// The timer class. A simple chronometer.
|
|
#[derive(Debug, Clone)]
|
|
pub struct Timer {
|
|
duration: f64,
|
|
target: Instant,
|
|
}
|
|
|
|
impl Timer {
|
|
pub fn new(duration: f64) -> Self {
|
|
let mut timer = Self { duration, target: Instant::now() };
|
|
timer.start();
|
|
timer
|
|
}
|
|
|
|
pub fn start(&mut self) {
|
|
self.target = Instant::now() + std::time::Duration::from_secs_f64(self.duration.max(0.0));
|
|
}
|
|
|
|
pub fn reset(&mut self, duration: Option<f64>) {
|
|
if let Some(duration) = duration {
|
|
self.set(duration);
|
|
}
|
|
self.start();
|
|
}
|
|
|
|
/// Elapsed seconds since the timer was started.
|
|
pub fn get(&self) -> f64 {
|
|
self.duration - self.target.saturating_duration_since(Instant::now()).as_secs_f64()
|
|
}
|
|
|
|
pub fn set(&mut self, duration: f64) {
|
|
self.duration = duration;
|
|
}
|
|
|
|
pub fn duration(&self) -> f64 {
|
|
self.duration
|
|
}
|
|
|
|
pub fn finished(&self) -> bool {
|
|
Instant::now() > self.target
|
|
}
|
|
}
|
|
|
|
/// The counter class, used to log durations.
|
|
#[derive(Debug, Clone)]
|
|
pub struct Counter {
|
|
start: Instant,
|
|
}
|
|
|
|
impl Default for Counter {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Counter {
|
|
pub fn new() -> Self {
|
|
Self { start: Instant::now() }
|
|
}
|
|
|
|
pub fn reset(&mut self) {
|
|
self.start = Instant::now();
|
|
}
|
|
|
|
pub fn get(&self) -> f64 {
|
|
self.start.elapsed().as_secs_f64()
|
|
}
|
|
}
|
|
|
|
fn last_update_times() -> &'static Mutex<HashMap<String, Instant>> {
|
|
static MAP: OnceLock<Mutex<HashMap<String, Instant>>> = OnceLock::new();
|
|
MAP.get_or_init(|| Mutex::new(HashMap::new()))
|
|
}
|
|
|
|
/// Return the elapsed time since the last update for the given key.
|
|
///
|
|
/// The first call for a key returns 1 second, mirroring the Python
|
|
/// implementation.
|
|
pub fn get_time_since_last_update(key: &str) -> f64 {
|
|
let now = Instant::now();
|
|
let mut map = last_update_times().lock().unwrap();
|
|
let since = match map.get(key) {
|
|
Some(last) => now.duration_since(*last).as_secs_f64(),
|
|
None => 1.0,
|
|
};
|
|
map.insert(key.to_string(), now);
|
|
since
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn timer_finished() {
|
|
let timer = Timer::new(0.0);
|
|
std::thread::sleep(std::time::Duration::from_millis(5));
|
|
assert!(timer.finished());
|
|
}
|
|
|
|
#[test]
|
|
fn time_since_first_call_is_one() {
|
|
let v = get_time_since_last_update("test-key");
|
|
assert_eq!(v, 1.0);
|
|
}
|
|
}
|