///|
/// Render one benchmark suite as a readable terminal report.
pub fn benchmark_suite_text(suite : BenchmarkSuite) -> String {
let out : Array[String] = [
"MoonBit VCD benchmark",
"fixture: " + suite.fixture,
]
for result in suite.results {
out.push("- " + result.to_text())
}
out.join("\n")
}
///|
/// Render one result as a machine-readable JSON object.
pub fn benchmark_result_json(result : BenchmarkResult) -> String {
"{\"name\":\"" +
escape_text(result.name) +
"\",\"iterations\":" +
result.iterations.to_string() +
",\"input_chars\":" +
result.input_chars.to_string() +
",\"parsed_traces\":" +
result.parsed_traces.to_string() +
",\"observed_changes\":" +
result.observed_changes.to_string() +
",\"checksum\":" +
result.checksum.to_string() +
"}"
}
///|
/// Render a complete benchmark suite as deterministic JSON.
pub fn benchmark_suite_json(suite : BenchmarkSuite) -> String {
"{\"fixture\":\"" +
escape_text(suite.fixture) +
"\",\"results\":[" +
suite.results.map(benchmark_result_json).join(",") +
"]}"
}
///|
/// Render benchmark results as a Markdown table suitable for reports.
pub fn benchmark_suite_markdown(suite : BenchmarkSuite) -> String {
let out : Array[String] = [
"## Benchmark",
"",
"Fixture: `" + suite.fixture + "`",
"",
"| Operation | Iterations | Input chars | Parsed | Changes | Checksum |",
"| --- | ---: | ---: | ---: | ---: | ---: |",
]
for result in suite.results {
out.push(
"| " +
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")
}
///|
/// Return a compact CSV row for every benchmark operation.
pub fn benchmark_rows(suite : BenchmarkSuite) -> Array[String] {
suite.results.map(fn(result) {
suite.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()
})
}
///|
/// Sum the stable checksums of all operations in a suite.
pub fn benchmark_checksum(suite : BenchmarkSuite) -> Int64 {
suite.results.fold(init=0L, fn(total, result) { total + result.checksum })
}
///|
/// Return the number of source characters in a generated fixture.
pub fn fixture_size_report(signal_count : Int, time_count : Int) -> String {
let fixture = synthetic_vcd(signal_count, time_count)
"signals=" +
Int::max(1, signal_count).to_string() +
" times=" +
Int::max(1, time_count).to_string() +
" chars=" +
fixture.length().to_string()
}
///|
/// Compare two benchmark runs by stable checksum and operation names.
pub fn benchmark_suite_compatible(
left : BenchmarkSuite,
right : BenchmarkSuite,
) -> Bool {
if left.results.length() != right.results.length() {
return false
}
for index in 0.. Double {
if result.parsed_traces == 0 {
0.0
} else {
result.observed_changes.to_double() / result.parsed_traces.to_double()
}
}
///|
/// Produce a human-readable benchmark verdict for CI logs.
pub fn benchmark_verdict(suite : BenchmarkSuite) -> String {
if suite.results.length() == 0 {
"empty benchmark suite"
} else if benchmark_checksum(suite) == 0L {
"benchmark produced a zero checksum"
} else {
"ok checksum=" + benchmark_checksum(suite).to_string()
}
}