openvm_circuit/metrics/cycle_tracker/
mod.rs

1#[derive(Clone, Debug, Default)]
2pub struct CycleTracker {
3    /// Stack of span names, with most recent at the end
4    stack: Vec<String>,
5}
6
7impl CycleTracker {
8    pub fn new() -> Self {
9        Self::default()
10    }
11
12    pub fn top(&self) -> Option<&String> {
13        self.stack.last()
14    }
15
16    /// Starts a new cycle tracker span for the given name.
17    /// If a span already exists for the given name, it ends the existing span and pushes a new one
18    /// to the vec.
19    pub fn start(&mut self, mut name: String) {
20        // hack to remove "CT-" prefix
21        if name.starts_with("CT-") {
22            name = name.split_off(3);
23        }
24        self.stack.push(name);
25    }
26
27    /// Ends the cycle tracker span for the given name.
28    /// If no span exists for the given name, it panics.
29    pub fn end(&mut self, mut name: String) {
30        // hack to remove "CT-" prefix
31        if name.starts_with("CT-") {
32            name = name.split_off(3);
33        }
34        let stack_top = self.stack.pop();
35        assert_eq!(stack_top.unwrap(), name, "Stack top does not match name");
36    }
37
38    /// Ends the current cycle tracker span.
39    pub fn force_end(&mut self) {
40        self.stack.pop();
41    }
42
43    /// Get full name of span with all parent names separated by ";" in flamegraph format
44    pub fn get_full_name(&self) -> String {
45        self.stack.join(";")
46    }
47}
48
49#[cfg(feature = "metrics")]
50mod emit {
51    use metrics::counter;
52
53    use super::CycleTracker;
54
55    impl CycleTracker {
56        pub fn increment_opcode(&self, (dsl_ir, opcode): &(Option<String>, String)) {
57            let labels = [
58                ("opcode", opcode.clone()),
59                ("dsl_ir", dsl_ir.clone().unwrap_or_default()),
60                ("cycle_tracker_span", self.get_full_name()),
61            ];
62            counter!("frequency", &labels).increment(1u64);
63        }
64
65        pub fn increment_cells_used(
66            &self,
67            (dsl_ir, opcode, air_name): &(Option<String>, String, String),
68            trace_cells_used: usize,
69        ) {
70            if trace_cells_used == 0 {
71                return;
72            }
73            let labels = [
74                ("air_name", air_name.clone()),
75                ("opcode", opcode.clone()),
76                ("dsl_ir", dsl_ir.clone().unwrap_or_default()),
77                ("cycle_tracker_span", self.get_full_name()),
78            ];
79            counter!("cells_used", &labels).increment(trace_cells_used as u64);
80        }
81    }
82}