///|
fn main {
let args = @env.args()
let repeat = find_repeat_arg(args)
let sample_count = find_samples_arg(args)
let warmup_count = find_warmup_arg(args)
guard repeat > 0 else { abort("repeat must be positive") }
guard sample_count >= 0 else { abort("samples must be non-negative") }
guard warmup_count >= 0 else { abort("warmup must be non-negative") }
match find_case_arg(args) {
Some(case_id) =>
match @support.find_case(case_id) {
Some(case_item) => {
let case_path = find_case_path_arg(args).unwrap_or(
"bench/datasets/cases/" + case_item.id + ".json",
)
let prepared = @support.prepare_case_from_fixture(
case_item, case_path,
)
let scratch = case_item.mutation_policy == "scratch_per_sample"
if sample_count == 0 {
let checksum = run_repeat(prepared, repeat, scratch)
println(@support.case_diagnostic_payload(case_item, checksum))
} else {
run_warmup(prepared, repeat, warmup_count, scratch)
let samples = collect_samples(
prepared, repeat, sample_count, scratch,
)
println(benchmark_payload(case_item, samples, repeat))
}
}
None => abort("unknown benchmark case: " + case_id)
}
None =>
abort(
"usage: moon run src/perf_runner [--case-file ] [--repeat ] [--samples ] [--warmup ]",
)
}
}
///|
fn find_case_arg(args : Array[String]) -> String? {
let mut skip_next = false
for candidate in args {
if skip_next {
skip_next = false
continue
}
if candidate == "--repeat" ||
candidate == "--samples" ||
candidate == "--warmup" ||
candidate == "--case-file" {
skip_next = true
continue
}
if @support.find_case(candidate) is Some(_) {
return Some(candidate)
}
}
None
}
///|
fn find_case_path_arg(args : Array[String]) -> String? {
for i = 0; i + 1 < args.length(); i = i + 1 {
if args[i] == "--case-file" {
return Some(args[i + 1])
}
}
None
}
///|
fn find_repeat_arg(args : Array[String]) -> Int32 {
find_flag_arg(args, "--repeat").unwrap_or(1)
}
///|
fn find_samples_arg(args : Array[String]) -> Int32 {
find_flag_arg(args, "--samples").unwrap_or(0)
}
///|
fn find_warmup_arg(args : Array[String]) -> Int32 {
find_flag_arg(args, "--warmup").unwrap_or(0)
}
///|
fn find_flag_arg(args : Array[String], flag : String) -> Int32? {
for i = 0; i + 1 < args.length(); i = i + 1 {
if args[i] == flag {
return Some(parse_int_arg(flag, args[i + 1]))
}
}
None
}
///|
fn parse_int_arg(flag : String, value : String) -> Int32 {
try @string.parse_int(value) catch {
_ => abort("invalid value for " + flag + ": " + value)
} noraise {
parsed => parsed
}
}
///|
fn run_repeat(
case_item : @support.PreparedCase,
repeat : Int32,
scratch : Bool,
) -> UInt64 {
let scratch_cases = prepare_repeat_cases(case_item, repeat, scratch)
run_prepared_cases(scratch_cases)
}
///|
fn run_warmup(
case_item : @support.PreparedCase,
repeat : Int32,
warmup_count : Int32,
scratch : Bool,
) -> Unit {
for _ in 0.. Array[Int32] {
let samples = []
for _ in 0.. Array[@support.PreparedCase] {
let out = []
for _ in 0.. UInt64 {
let mut checksum = 1469598103934665603UL
for case_item in cases {
let value = @support.run_prepared_case_inplace(case_item, false)
checksum = (checksum ^ value) * 1099511628211UL
}
checksum
}
///|
fn benchmark_payload(
case_item : @support.Case,
samples : Array[Int32],
repeat : Int32,
) -> String {
"{\"kind\":\"benchmark\",\"dataset_version\":\"" +
@support.dataset_version +
"\",\"case_id\":\"" +
case_item.id +
"\",\"operation\":\"" +
case_item.operation +
"\",\"family\":\"" +
case_item.family +
"\",\"workload_tier\":\"" +
case_item.workload_tier +
"\",\"structure\":\"" +
case_item.structure +
"\",\"timing_scope\":\"" +
case_item.timing_scope +
"\",\"input_layout\":\"" +
case_item.input_layout +
"\",\"mutation_policy\":\"" +
case_item.mutation_policy +
"\",\"size_tier\":\"" +
case_item.size_tier +
"\",\"cost_model\":\"" +
case_item.cost_model +
"\",\"rows\":" +
case_item.rows.to_string() +
",\"cols\":" +
case_item.cols.to_string() +
",\"rhs_cols\":" +
case_item.rhs_cols.to_string() +
",\"repeat\":" +
repeat.to_string() +
",\"samples\":" +
int_array_json(samples) +
"}"
}
///|
fn int_array_json(values : Array[Int32]) -> String {
let mut out = "["
for i = 0; i < values.length(); i = i + 1 {
if i > 0 {
out = out + ","
}
out = out + values[i].to_string()
}
out + "]"
}