///|
/// Deterministic operation counters used by the benchmark CLI and CI.
pub struct BenchmarkResult {
name : String
iterations : Int
input_chars : Int
parsed_traces : Int
observed_changes : Int
checksum : Int64
} derive(Debug, Eq)
///|
/// A collection of benchmark results for one fixture.
pub struct BenchmarkSuite {
fixture : String
results : Array[BenchmarkResult]
} derive(Debug, Eq)
///|
/// Build a repeatable VCD fixture with scalar and vector signals.
pub fn synthetic_vcd(signal_count : Int, time_count : Int) -> String {
let signals = Int::max(1, signal_count)
let times = Int::max(1, time_count)
let out = StringBuilder()
out.write_string("$date benchmark $end\n")
out.write_string("$version moonbit-vcd $end\n")
out.write_string("$timescale 1ns $end\n")
out.write_string("$scope module bench $end\n")
for signal in 0.. BenchmarkResult {
let safe_iterations = Int::max(1, iterations)
let mut parsed = 0
let mut changes = 0
let mut checksum : Int64 = 0L
for _ in 0.. {
parsed += 1
changes += trace.changes.length()
checksum += trace.end_time + trace.signals.length().to_int64()
}
Err(_) => checksum -= 1L
}
}
{
name: "parse",
iterations: safe_iterations,
input_chars: input.length(),
parsed_traces: parsed,
observed_changes: changes,
checksum,
}
}
///|
/// Run repeated indexed queries over a parsed fixture.
pub fn benchmark_queries(trace : Trace, iterations : Int) -> BenchmarkResult {
let safe_iterations = Int::max(1, iterations)
let index = build_index(trace)
let mut changes = 0
let mut checksum : Int64 = 0L
for _ in 0.. value.width().to_int64()
None => 0L
}
}
}
{
name: "indexed-queries",
iterations: safe_iterations,
input_chars: 0,
parsed_traces: 1,
observed_changes: changes,
checksum,
}
}
///|
/// Run repeated edge and state analysis over a parsed fixture.
pub fn benchmark_analysis(trace : Trace, iterations : Int) -> BenchmarkResult {
let safe_iterations = Int::max(1, iterations)
let mut transitions = 0
let mut checksum : Int64 = 0L
for _ in 0.. BenchmarkSuite {
let fixture = synthetic_vcd(signal_count, time_count)
let parsed = match parse(fixture) {
Ok(trace) => trace
Err(_) =>
{
header: { date: None, version: None, timescale: None, comment: None },
signals: [],
changes: [],
end_time: 0L,
}
}
{
fixture: "synthetic-" +
signal_count.to_string() +
"x" +
time_count.to_string(),
results: [
benchmark_parse(fixture, iterations),
benchmark_queries(parsed, iterations),
benchmark_analysis(parsed, iterations),
],
}
}
///|
/// Render benchmark counters as stable text.
pub fn BenchmarkResult::to_text(self : BenchmarkResult) -> String {
self.name +
" iterations=" +
self.iterations.to_string() +
" input_chars=" +
self.input_chars.to_string() +
" parsed=" +
self.parsed_traces.to_string() +
" changes=" +
self.observed_changes.to_string() +
" checksum=" +
self.checksum.to_string()
}
///|
/// Render a suite as CSV for archival benchmark evidence.
pub fn BenchmarkSuite::to_csv(self : BenchmarkSuite) -> String {
let out : Array[String] = [
"fixture,name,iterations,input_chars,parsed,changes,checksum",
]
for result in self.results {
out.push(
self.fixture +
"," +
result.name +
"," +
result.iterations.to_string() +
"," +
result.input_chars.to_string() +
"," +
result.parsed_traces.to_string() +
"," +
result.observed_changes.to_string() +
"," +
result.checksum.to_string(),
)
}
out.join("\n")
}