pub struct PerformanceMonitor {
pub instruction_count: usize,
pub call_count: usize,
pub max_stack_depth: usize,
pub start_time: Option<std::time::Instant>,
pub memory_allocations: usize,
pub memory_deallocations: usize,
pub gc_count: usize,
pub gc_total_time_us: u64,
pub max_memory_used: usize,
pub enabled: bool,
}
impl PerformanceMonitor {
pub fn new() -> Self {
Self {
instruction_count: 0,
call_count: 0,
max_stack_depth: 0,
start_time: None,
memory_allocations: 0,
memory_deallocations: 0,
gc_count: 0,
gc_total_time_us: 0,
max_memory_used: 0,
enabled: true,
}
}
pub fn start(&mut self) {
self.start_time = Some(std::time::Instant::now());
self.instruction_count = 0;
self.call_count = 0;
self.max_stack_depth = 0;
self.memory_allocations = 0;
self.memory_deallocations = 0;
self.gc_count = 0;
self.gc_total_time_us = 0;
self.max_memory_used = 0;
}
pub fn record_instruction(&mut self) {
if !self.enabled {
return;
}
self.instruction_count += 1;
}
pub fn record_call(&mut self, stack_depth: usize) {
if !self.enabled {
return;
}
self.call_count += 1;
if stack_depth > self.max_stack_depth {
self.max_stack_depth = stack_depth;
}
}
pub fn record_memory_allocation(&mut self, size: usize) {
if !self.enabled {
return;
}
self.memory_allocations += 1;
}
pub fn record_memory_deallocation(&mut self, size: usize) {
if !self.enabled {
return;
}
self.memory_deallocations += 1;
}
pub fn record_gc(&mut self, duration_us: u64) {
if !self.enabled {
return;
}
self.gc_count += 1;
self.gc_total_time_us += duration_us;
}
pub fn update_max_memory_used(&mut self, current_used: usize) {
if !self.enabled {
return;
}
if current_used > self.max_memory_used {
self.max_memory_used = current_used;
}
}
pub fn enable(&mut self) {
self.enabled = true;
}
pub fn disable(&mut self) {
self.enabled = false;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn elapsed_us(&self) -> u64 {
self.start_time.map(|t| t.elapsed().as_micros() as u64).unwrap_or(0)
}
pub fn report(&self) -> String {
let elapsed = self.elapsed_us();
let instructions_per_us = if elapsed > 0 { self.instruction_count as f64 / elapsed as f64 } else { 0.0 };
format!(
"Performance Report:\n\
- Instructions executed: {}\n\
- Function calls: {}\n\
- Max stack depth: {}\n\
- Execution time: {} us\
- Instructions per us: {:.2}\n\
- Memory allocations: {}\n\
- Memory deallocations: {}\n\
- Garbage collections: {}\n\
- GC total time: {} us\
- Max memory used: {} bytes",
self.instruction_count,
self.call_count,
self.max_stack_depth,
elapsed,
instructions_per_us,
self.memory_allocations,
self.memory_deallocations,
self.gc_count,
self.gc_total_time_us,
self.max_memory_used
)
}
}
impl Default for PerformanceMonitor {
fn default() -> Self {
Self::new()
}
}