M1: core engine, config, plugin model and core plugins
- 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
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
//! 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user