// Performance counters and statistics tracking
///|
pub(all) struct Counter {
name : String
value : Int
}
///|
pub fn Counter::new(name : String) -> Counter {
Counter::{ name, value: 0 }
}
///|
pub fn Counter::increment(self : Counter) -> Counter {
Counter::{ ..self, value: self.value + 1 }
}
///|
pub fn Counter::add(self : Counter, n : Int) -> Counter {
Counter::{ ..self, value: self.value + n }
}
///|
pub fn Counter::read(self : Counter) -> Int {
self.value
}
// Timer — measure elapsed ticks between start and stop
///|
pub(all) struct Timer {
name : String
start_seq : Int
}
///|
pub fn Timer::start(name : String, current_seq : Int) -> Timer {
Timer::{ name, start_seq: current_seq }
}
///|
pub fn Timer::stop(self : Timer, current_seq : Int) -> (String, Int) {
(self.name, current_seq - self.start_seq)
}
// Histogram — track distribution of values
///|
pub(all) struct Histogram {
name : String
values : Array[Int]
}
///|
pub fn Histogram::new(name : String) -> Histogram {
Histogram::{ name, values: [] }
}
///|
pub fn Histogram::record(self : Histogram, value : Int) -> Histogram {
let new_values = self.values.copy()
new_values.push(value)
Histogram::{ ..self, values: new_values }
}
///|
pub fn Histogram::count(self : Histogram) -> Int {
self.values.length()
}
///|
pub fn Histogram::sum(self : Histogram) -> Int {
histo_sum(self.values, 0, 0)
}
///|
fn histo_sum(values : Array[Int], idx : Int, acc : Int) -> Int {
if idx >= values.length() {
acc
} else {
histo_sum(values, idx + 1, acc + values[idx])
}
}
///|
pub fn Histogram::avg(self : Histogram) -> Int {
if self.values.length() == 0 {
0
} else {
self.sum() / self.values.length()
}
}
///|
pub fn Histogram::min_val(self : Histogram) -> Int {
if self.values.length() == 0 {
0
} else {
histo_min(self.values, 1, self.values[0])
}
}
///|
fn histo_min(values : Array[Int], idx : Int, cur_min : Int) -> Int {
if idx >= values.length() {
cur_min
} else if values[idx] < cur_min {
histo_min(values, idx + 1, values[idx])
} else {
histo_min(values, idx + 1, cur_min)
}
}
///|
pub fn Histogram::max_val(self : Histogram) -> Int {
if self.values.length() == 0 {
0
} else {
histo_max(self.values, 1, self.values[0])
}
}
///|
fn histo_max(values : Array[Int], idx : Int, cur_max : Int) -> Int {
if idx >= values.length() {
cur_max
} else if values[idx] > cur_max {
histo_max(values, idx + 1, values[idx])
} else {
histo_max(values, idx + 1, cur_max)
}
}