veryl-analyzer 0.20.1

A modern hardware description language
Documentation
use crate::HashMap;
use miette::{self, IntoDiagnostic, Result, WrapErr};
use serde::Serialize;
use std::fs;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

#[derive(Clone, Default, Serialize)]
pub struct ConvStats {
    pub count: u64,
    pub total_us: u64,
    pub avg_us: u64,
    pub min_us: u64,
    pub max_us: u64,
}

#[derive(Clone, Default)]
pub struct ConvProfile {
    pub entries: HashMap<String, ConvStats>,
}

impl ConvProfile {
    pub fn record(&mut self, name: &str, duration: Duration) {
        let us = duration.as_micros() as u64;
        let entry = self.entries.entry(name.to_string()).or_default();
        if entry.count == 0 {
            entry.min_us = us;
            entry.max_us = us;
        } else {
            entry.min_us = entry.min_us.min(us);
            entry.max_us = entry.max_us.max(us);
        }
        entry.total_us += us;
        entry.count += 1;
        entry.avg_us = entry.total_us / entry.count;
    }

    pub fn to_toml_file(&self, path: &str) -> Result<()> {
        let toml_string = self.to_toml_string();
        fs::write(path, toml_string)
            .into_diagnostic()
            .wrap_err(format!("Failed to write conv profile to {path}"))
    }

    pub fn to_toml_string(&self) -> String {
        use std::collections::BTreeMap;
        let output: BTreeMap<_, _> = self.entries.iter().collect();
        toml::to_string(&output).unwrap_or_default()
    }
}

pub struct ConvProfileGuard {
    profiler: Arc<Mutex<ConvProfile>>,
    name: String,
    start: Instant,
}

impl ConvProfileGuard {
    pub fn new(profiler: Arc<Mutex<ConvProfile>>, name: impl Into<String>) -> Self {
        Self {
            profiler,
            name: name.into(),
            start: Instant::now(),
        }
    }
}

impl Drop for ConvProfileGuard {
    fn drop(&mut self) {
        if let Ok(mut p) = self.profiler.lock() {
            p.record(&self.name, self.start.elapsed());
        }
    }
}