///|
/// Derived benchmark statistics used in human-readable performance reports.
pub struct BenchmarkSummary {
scenarios : Int
total_operations : Int
total_tokens : Int
total_input_bytes : Int
total_output_bytes : Int
total_elapsed_units : UInt64
fastest_scenario : String
largest_scenario : String
} derive(Debug, Eq)
///|
pub fn BenchmarkReport::summary(self : BenchmarkReport) -> BenchmarkSummary {
let mut operations = 0
let mut tokens = 0
let mut input = 0
let mut output = 0
let mut elapsed : UInt64 = 0
let mut fastest = ""
let mut fastest_units : UInt64 = 18446744073709551615
let mut largest = ""
let mut largest_bytes = 0
for measurement in self.measurements {
operations += measurement.operations
tokens += measurement.token_count
input += measurement.input_bytes
output += measurement.output_bytes
elapsed += measurement.elapsed_units
if measurement.elapsed_units < fastest_units {
fastest_units = measurement.elapsed_units
fastest = measurement.name
}
if measurement.input_bytes > largest_bytes {
largest_bytes = measurement.input_bytes
largest = measurement.name
}
}
{
scenarios: self.measurements.length(),
total_operations: operations,
total_tokens: tokens,
total_input_bytes: input,
total_output_bytes: output,
total_elapsed_units: elapsed,
fastest_scenario: fastest,
largest_scenario: largest,
}
}
///|
pub fn BenchmarkSummary::average_tokens(self : BenchmarkSummary) -> Int {
if self.scenarios == 0 {
0
} else {
self.total_tokens / self.scenarios
}
}
///|
pub fn BenchmarkSummary::average_input_bytes(self : BenchmarkSummary) -> Int {
if self.scenarios == 0 {
0
} else {
self.total_input_bytes / self.scenarios
}
}
///|
pub fn BenchmarkSummary::average_output_bytes(self : BenchmarkSummary) -> Int {
if self.scenarios == 0 {
0
} else {
self.total_output_bytes / self.scenarios
}
}
///|
pub fn BenchmarkSummary::output_expansion_percent(
self : BenchmarkSummary,
) -> Int {
if self.total_input_bytes == 0 {
0
} else {
self.total_output_bytes * 100 / self.total_input_bytes
}
}
///|
pub fn BenchmarkSummary::is_measured(self : BenchmarkSummary) -> Bool {
self.scenarios > 0 && self.total_elapsed_units > 0
}
///|
pub fn BenchmarkSummary::to_markdown(self : BenchmarkSummary) -> String {
"| Aggregate metric | Value |\n| --- | ---: |\n" +
"| Scenarios | " +
self.scenarios.to_string() +
" |\n" +
"| Operations | " +
self.total_operations.to_string() +
" |\n" +
"| Tokens | " +
self.total_tokens.to_string() +
" |\n" +
"| Input bytes | " +
self.total_input_bytes.to_string() +
" |\n" +
"| Output bytes | " +
self.total_output_bytes.to_string() +
" |\n" +
"| Elapsed units | " +
self.total_elapsed_units.to_string() +
" |\n" +
"| Fastest scenario | " +
self.fastest_scenario +
" |\n" +
"| Largest input | " +
self.largest_scenario +
" |"
}
///|
pub fn BenchmarkSummary::to_json(self : BenchmarkSummary) -> String {
"{\"scenarios\":" +
self.scenarios.to_string() +
",\"operations\":" +
self.total_operations.to_string() +
",\"tokens\":" +
self.total_tokens.to_string() +
",\"inputBytes\":" +
self.total_input_bytes.to_string() +
",\"outputBytes\":" +
self.total_output_bytes.to_string() +
",\"elapsedUnits\":" +
self.total_elapsed_units.to_string() +
",\"fastest\":\"" +
json_escape(self.fastest_scenario) +
"\"}"
}
///|
pub fn BenchmarkReport::summary_markdown(self : BenchmarkReport) -> String {
self.summary().to_markdown()
}
///|
pub fn BenchmarkReport::summary_json(self : BenchmarkReport) -> String {
self.summary().to_json()
}
///|
pub fn BenchmarkReport::is_comparable(self : BenchmarkReport) -> Bool {
self.measurements.length() >= 2 && self.summary().is_measured()
}
///|
pub fn BenchmarkReport::scenario_names(self : BenchmarkReport) -> Array[String] {
self.measurements.map(fn(measurement) { measurement.name })
}
///|
pub fn BenchmarkReport::measurement_named(
self : BenchmarkReport,
name : String,
) -> BenchmarkMeasurement? {
for measurement in self.measurements {
if measurement.name == name {
return Some(measurement)
}
}
None
}
///|
pub fn BenchmarkReport::slowest(
self : BenchmarkReport,
) -> BenchmarkMeasurement? {
if self.measurements.length() == 0 {
None
} else {
let mut result = self.measurements[0]
for measurement in self.measurements {
if measurement.elapsed_units > result.elapsed_units {
result = measurement
}
}
Some(result)
}
}
///|
pub fn BenchmarkReport::largest_input(
self : BenchmarkReport,
) -> BenchmarkMeasurement? {
if self.measurements.length() == 0 {
None
} else {
let mut result = self.measurements[0]
for measurement in self.measurements {
if measurement.input_bytes > result.input_bytes {
result = measurement
}
}
Some(result)
}
}