miden_debug_engine/profiling/instrument/
op_histogram_proc.rs1use alloc::{borrow::ToOwned, string::String, vec::Vec};
2
3#[cfg(feature = "std")]
4type Map<K, V> = std::collections::HashMap<K, V>;
5#[cfg(not(feature = "std"))]
6type Map<K, V> = alloc::collections::BTreeMap<K, V>;
7
8use miden_core::operations::Operation;
9
10use super::{Instrument, InstrumentRegistration};
11use crate::profiling::{OutputResult, OutputWriter, helpers::op_histogram::OpHistogram};
12
13const UNKNOWN_PROCEDURE: &str = "<unknown>";
16
17#[derive(Default)]
26pub struct OpHistogramProc {
27 histograms: Map<String, OpHistogram>,
28}
29
30impl InstrumentRegistration for OpHistogramProc {
31 const NAME: &'static str = "op-histogram-proc";
32
33 fn build(_config: &crate::profiling::ProfilerConfig) -> Result<Self, super::InstrumentError> {
34 Ok(Self::default())
35 }
36}
37
38#[cfg(feature = "std")]
39crate::register_instrument!(OpHistogramProc);
40
41impl Instrument for OpHistogramProc {
42 fn name(&self) -> &'static str {
43 Self::NAME
44 }
45
46 fn on_operation_execution_cycle(&mut self, op: Operation, proc: Option<&str>) {
47 let key = proc.unwrap_or(UNKNOWN_PROCEDURE);
48 match self.histograms.get_mut(key) {
50 Some(hist) => hist.record(op),
51 None => {
52 let mut hist = OpHistogram::default();
53 hist.record(op);
54 self.histograms.insert(key.to_owned(), hist);
55 }
56 }
57 }
58
59 fn write_report_to(&self, writer: &mut dyn OutputWriter) -> OutputResult<()> {
60 let mut entries: Vec<(&str, &OpHistogram)> =
61 self.histograms.iter().map(|(name, hist)| (name.as_str(), hist)).collect();
62 entries
65 .sort_by(|a, b| b.1.total_cycles().cmp(&a.1.total_cycles()).then_with(|| a.0.cmp(b.0)));
66
67 for (name, hist) in entries {
68 writeln!(writer, "procedure: {name}")?;
69 writer.write_all(hist.report().as_bytes())?;
70 }
71 Ok(())
72 }
73}
74
75#[cfg(test)]
76mod tests;