runmat_vm/interpreter/
timing.rs1#[cfg(not(target_arch = "wasm32"))]
2use runmat_time::Instant;
3
4#[cfg(not(target_arch = "wasm32"))]
5pub struct InterpreterTiming {
6 enabled: bool,
7 host_span_start: Option<(Instant, usize)>,
8 host_span_last_pc: Option<usize>,
9 host_span_instrs: u64,
10 seq: u64,
11}
12
13#[cfg(not(target_arch = "wasm32"))]
14impl InterpreterTiming {
15 pub fn new() -> Self {
16 let enabled = std::env::var("RUNMAT_INTERPRETER_TIMING")
17 .map(|v| v == "1" || v.eq_ignore_ascii_case("true") || v.eq_ignore_ascii_case("yes"))
18 .unwrap_or(false);
19 Self {
20 enabled,
21 host_span_start: None,
22 host_span_last_pc: None,
23 host_span_instrs: 0,
24 seq: 0,
25 }
26 }
27
28 pub fn note_host_instr(&mut self, pc: usize) {
29 if !self.enabled {
30 return;
31 }
32 if self.host_span_start.is_none() {
33 self.host_span_start = Some((Instant::now(), pc));
34 self.host_span_instrs = 0;
35 }
36 self.host_span_instrs += 1;
37 self.host_span_last_pc = Some(pc);
38 }
39
40 pub fn flush_host_span(&mut self, reason: &str, detail: Option<&str>) {
41 if !self.enabled {
42 return;
43 }
44 let Some((start, start_pc)) = self.host_span_start.take() else {
45 return;
46 };
47 let duration = start.elapsed();
48 let end_pc = self.host_span_last_pc.unwrap_or(start_pc);
49 let instrs = self.host_span_instrs.max(1);
50 if let Some(extra) = detail {
51 log::debug!(
52 "interpreter_host_span seq={} reason={} detail={} pc_span=[{}..{}] instrs={} duration_ns={}",
53 self.seq,
54 reason,
55 extra,
56 start_pc,
57 end_pc,
58 instrs,
59 duration.as_nanos()
60 );
61 } else {
62 log::debug!(
63 "interpreter_host_span seq={} reason={} pc_span=[{}..{}] instrs={} duration_ns={}",
64 self.seq,
65 reason,
66 start_pc,
67 end_pc,
68 instrs,
69 duration.as_nanos()
70 );
71 }
72 self.seq += 1;
73 self.host_span_last_pc = None;
74 self.host_span_instrs = 0;
75 }
76}
77
78#[cfg(not(target_arch = "wasm32"))]
79impl Default for InterpreterTiming {
80 fn default() -> Self {
81 Self::new()
82 }
83}
84
85#[cfg(not(target_arch = "wasm32"))]
86impl Drop for InterpreterTiming {
87 fn drop(&mut self) {
88 self.flush_host_span("drop", None);
89 }
90}
91
92#[cfg(target_arch = "wasm32")]
93pub struct InterpreterTiming;
94
95#[cfg(target_arch = "wasm32")]
96impl InterpreterTiming {
97 pub fn new() -> Self {
98 Self
99 }
100
101 pub fn note_host_instr(&mut self, _pc: usize) {}
102
103 pub fn flush_host_span(&mut self, _reason: &str, _detail: Option<&str>) {}
104}
105
106#[cfg(target_arch = "wasm32")]
107impl Default for InterpreterTiming {
108 fn default() -> Self {
109 Self::new()
110 }
111}
112
113#[cfg(target_arch = "wasm32")]
114impl Drop for InterpreterTiming {
115 fn drop(&mut self) {}
116}