corsa 0.15.0

Production-oriented Rust bindings, orchestration layers, and Node integration for Corsa
Documentation
use std::{
    collections::BTreeMap,
    sync::{Mutex, MutexGuard},
    time::Duration,
};

use corsa::{
    api::{ApiProfileEvent, ApiProfiler},
    fast::{CompactString, SmallVec},
};

use crate::stats::Stats;

#[derive(Clone, Debug)]
pub struct ScenarioProfileRow {
    pub method: CompactString,
    pub phase: CompactString,
    pub stats: Stats,
}

#[derive(Default)]
pub struct BenchProfiler {
    events: Mutex<SmallVec<[ApiProfileEvent; 32]>>,
}

impl BenchProfiler {
    pub fn clear(&self) {
        self.events().clear();
    }

    pub fn drain_iteration_totals(&self) -> BTreeMap<(CompactString, CompactString), Duration> {
        let mut events = self.events();
        let drained = std::mem::take(&mut *events);
        let mut totals = BTreeMap::<(CompactString, CompactString), Duration>::new();
        for event in drained {
            let key = (event.method, CompactString::from(event.phase.as_str()));
            totals
                .entry(key)
                .and_modify(|duration| *duration += event.duration)
                .or_insert(event.duration);
        }
        totals
    }

    fn events(&self) -> MutexGuard<'_, SmallVec<[ApiProfileEvent; 32]>> {
        self.events
            .lock()
            .unwrap_or_else(|poisoned| poisoned.into_inner())
    }
}

impl ApiProfiler for BenchProfiler {
    fn on_profile(&self, event: &ApiProfileEvent) {
        self.events().push(event.clone());
    }
}

pub fn summarize(
    samples: BTreeMap<(CompactString, CompactString), SmallVec<[Duration; 32]>>,
) -> SmallVec<[ScenarioProfileRow; 32]> {
    let mut rows = SmallVec::<[ScenarioProfileRow; 32]>::new();
    for ((method, phase), durations) in samples {
        rows.push(ScenarioProfileRow {
            method,
            phase,
            stats: Stats::from_samples(durations),
        });
    }
    rows
}