// =============================================================================
// Scenario helpers shared by both benchmark surfaces
//
// Two benchmark surfaces exist in this package:
//
// 1. Native @bench.T test blocks (benchmarks.mbt)
// Run with: moon test bench/ --target js
// Purpose: interactive development, automatic iteration detection,
// moon-native output, regression detection per-commit.
//
// 2. CLI runner using run_bench() from runner.mbt (main.mbt)
// Run with: moon run bench/main --target js [-- --all] [-- --csv]
// Purpose: CI baseline snapshots, CSV output for long-term tracking.
//
// Both surfaces share the JS workload strings from workloads.mbt and the
// verify() helper defined below.
//
// Benchmark category naming convention:
//
// exec/ Full interpreter pipeline (lex + parse + eval via @lib.run).
// Cost includes parse overhead; use for regression tracking of
// end-to-end execution paths the bytecode VM does not cover
// (e.g. for-of, async, generators).
//
// isolate/bytecode/ Pre-compiled bytecode program, interpreter excluded.
// Measures bytecode VM dispatch only; parse overhead removed.
// Use when the workload is supported by the bytecode compiler.
//
// Note: the bytecode VM does not yet support: for-of, async/await, generators,
// destructuring patterns, or labeled break/continue. Workloads for those paths
// must use the exec/ category.
// =============================================================================
///|
/// Verify that run(src) produces the expected result string.
///
/// Called once *outside* any timed region (before bench loops or before
/// b.bench() calls) to confirm the workload is exercising correct behaviour.
/// Aborts with a clear message on mismatch — a mismatch means the workload
/// constant or the interpreter has a bug, not a performance problem.
///
/// Not timed: the interpreter startup and parse cost here is intentionally
/// not representative; that cost is already covered by the pipeline benchmarks.
pub fn verify(src : String, expected : String) -> Unit raise {
let (_, got) = @lib.run(src)
if got != expected {
abort(
"bench correctness check failed\n source: (see workloads.mbt)\n expected: \{expected}\n got: \{got}",
)
}
}
// ---------------------------------------------------------------------------
// CLI runner scenarios (used by main.mbt via run_regression, run_all, etc.)
// ---------------------------------------------------------------------------
///|
pub fn bench_startup_tiny() -> BenchResult raise {
verify(STARTUP_TINY_SRC, "2")
run_bench(
"startup/tiny_program",
Regression,
{ warmup: 5, iterations: 50, group_size: 50, },
fn() raise { let _ = @lib.run(STARTUP_TINY_SRC) },
stage=Startup,
)
}
///|
pub fn bench_startup_parse_tiny() -> BenchResult raise {
let prog = @parser.parse(STARTUP_TINY_SRC)
let interp = @interpreter.new_interpreter()
let got = interp.run(prog.stmts).to_string()
if got != "2" {
abort(
"bench correctness check failed\n source: STARTUP_TINY_SRC parsed\n expected: 2\n got: \{got}",
)
}
run_bench(
"startup/phase/parse_tiny",
Component,
{ warmup: 5, iterations: 50, group_size: 10000, },
fn() raise { let _ = @parser.parse(STARTUP_TINY_SRC) },
stage=Frontend,
)
}
///|
pub fn bench_startup_new_interpreter() -> BenchResult raise {
let _ = @interpreter.new_interpreter()
run_bench(
"startup/phase/new_interpreter",
Component,
{ warmup: 5, iterations: 50, group_size: 10, },
fn() { let _ = @interpreter.new_interpreter() },
stage=Startup,
)
}
///|
pub fn bench_startup_execute_preparsed_tiny() -> BenchResult raise {
let prog = @parser.parse(STARTUP_TINY_SRC)
let precheck_interp = @interpreter.new_interpreter()
let got = precheck_interp.run(prog.stmts).to_string()
if got != "2" {
abort(
"bench correctness check failed\n source: STARTUP_TINY_SRC preparsed\n expected: 2\n got: \{got}",
)
}
let interp = @interpreter.new_interpreter()
run_bench(
"startup/phase/execute_preparsed_tiny",
Component,
{ warmup: 5, iterations: 50, group_size: 20000, },
fn() raise { let _ = interp.run(prog.stmts) },
)
}
///|
pub fn bench_startup_event_loop_drain_empty() -> BenchResult raise {
let prog = @parser.parse(STARTUP_TINY_SRC)
let interp = @interpreter.new_interpreter()
let got = interp.run(prog.stmts).to_string()
if got != "2" {
abort(
"bench correctness check failed\n source: STARTUP_TINY_SRC event loop drain\n expected: 2\n got: \{got}",
)
}
interp.run_microtasks()
interp.run_timers()
run_bench(
"startup/phase/event_loop_drain_empty",
Component,
{ warmup: 5, iterations: 50, group_size: 50000, },
fn() raise {
interp.run_microtasks()
interp.run_timers()
},
stage=Startup,
)
}
///|
pub fn bench_startup_result_stringify_output() -> BenchResult raise {
let prog = @parser.parse(STARTUP_TINY_SRC)
let interp = @interpreter.new_interpreter()
let result = interp.run(prog.stmts)
let got = result.to_string()
if got != "2" {
abort(
"bench correctness check failed\n source: STARTUP_TINY_SRC stringify\n expected: 2\n got: \{got}",
)
}
let output = interp.host.output
run_bench(
"startup/phase/result_stringify_output",
Component,
{ warmup: 5, iterations: 50, group_size: 1000000, },
fn() { let _ = (output, result.to_string()) },
)
}
///|
pub fn bench_lexer_small() -> BenchResult raise {
run_bench(
"lexer/small",
Regression,
{ warmup: 3, iterations: 100, group_size: 100, },
fn() raise { let _ = @lexer.tokenize(LEXER_SMALL_SRC) },
stage=Frontend,
)
}
///|
pub fn bench_lexer_large() -> BenchResult raise {
run_bench(
"lexer/large",
Regression,
{ warmup: 3, iterations: 50, group_size: 50, },
fn() raise { let _ = @lexer.tokenize(LEXER_LARGE_SRC) },
stage=Frontend,
)
}
///|
pub fn bench_fibonacci() -> BenchResult raise {
verify(FIBONACCI_SRC, "832040")
run_bench(
"exec/fibonacci_30",
Regression,
{ warmup: 2, iterations: 5, group_size: 1, },
fn() raise { let _ = @lib.run(FIBONACCI_SRC) },
)
}
///|
pub fn bench_property_chain() -> BenchResult raise {
verify(PROPERTY_CHAIN_SRC, "420000")
run_bench(
"exec/property_chain",
Regression,
{ warmup: 2, iterations: 8, group_size: 1, },
fn() raise { let _ = @lib.run(PROPERTY_CHAIN_SRC) },
)
}
///|
fn bench_regexp_retained_matcher() -> BenchResult raise {
verify(REGEXP_RETAINED_MATCHER_SRC, "512")
run_bench(
"regexp/retained_matcher",
Component,
{ warmup: 3, iterations: 20, group_size: 1, },
fn() raise { let _ = @lib.run(REGEXP_RETAINED_MATCHER_SRC) },
stage=Execution,
)
}
///|
pub fn bench_array_map_filter() -> BenchResult raise {
verify(ARRAY_MAP_FILTER_SRC, "334")
run_bench(
"exec/array_map_filter",
Component,
{ warmup: 2, iterations: 10, group_size: 1, },
fn() raise { let _ = @lib.run(ARRAY_MAP_FILTER_SRC) },
)
}
///|
pub fn bench_closure_factory() -> BenchResult raise {
verify(CLOSURE_FACTORY_SRC, "500500")
run_bench(
"exec/closure_factory",
Component,
{ warmup: 3, iterations: 20, group_size: 3, },
fn() raise { let _ = @lib.run(CLOSURE_FACTORY_SRC) },
)
}
///|
pub fn bench_closure_legacy_closure_factory() -> BenchResult raise {
verify(CLOSURE_FACTORY_SRC, "500500")
let prog = @parser.parse(CLOSURE_FACTORY_SRC)
let compiled = @compiler.compile_script_to_closure(prog.stmts)
let precheck_interp = @interpreter.new_interpreter()
let got = compiled(precheck_interp).to_string()
if got != "500500" {
abort(
"bench correctness check failed\n source: CLOSURE_FACTORY_SRC compiled\n expected: 500500\n got: \{got}",
)
}
run_bench(
"baseline/closure_legacy/closure_factory",
Component,
{ warmup: 3, iterations: 20, group_size: 3, },
fn() raise {
let interp = @interpreter.new_interpreter()
let _ = compiled(interp)
},
)
}
///|
pub fn bench_bytecode_closure_factory() -> BenchResult raise {
verify(CLOSURE_FACTORY_SRC, "500500")
let prog = @parser.parse(CLOSURE_FACTORY_SRC)
let bytecode = @compiler.compile_script_to_bytecode(prog.stmts)
let got = bytecode.run(@interpreter.new_interpreter()).to_string()
if got != "500500" {
abort(
"bench correctness check failed\n source: CLOSURE_FACTORY_SRC bytecode\n expected: 500500\n got: \{got}",
)
}
run_bench(
"baseline/bytecode/closure_factory",
Component,
{ warmup: 3, iterations: 20, group_size: 3, },
fn() raise {
let interp = @interpreter.new_interpreter()
let _ = bytecode.run(interp)
},
)
}
///|
fn prechecked_bytecode_program(
name : String,
src : String,
expected : String,
) -> @compiler.BytecodeProgram raise {
verify(src, expected)
let prog = @parser.parse(src)
let bytecode = @compiler.compile_script_to_bytecode(prog.stmts)
let got = bytecode.run(@interpreter.new_interpreter()).to_string()
if got != expected {
abort(
"bench correctness check failed\n source: \{name} bytecode\n expected: \{expected}\n got: \{got}",
)
}
bytecode
}
///|
fn bench_bytecode_micro(
name : String,
src : String,
expected : String,
) -> BenchResult raise {
let bytecode = prechecked_bytecode_program(name, src, expected)
let interp = @interpreter.new_interpreter()
run_bench(name, Component, { warmup: 3, iterations: 15, group_size: 3, }, fn() raise {
let _ = bytecode.run(interp)
})
}
///|
pub fn bench_bytecode_dispatch_stack() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/dispatch_stack",
BYTECODE_DISPATCH_STACK_SRC,
BYTECODE_MICRO_ACCESS_EXPECTED,
)
}
///|
pub fn bench_bytecode_local_access() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/local_access",
BYTECODE_LOCAL_ACCESS_SRC,
BYTECODE_MICRO_ACCESS_EXPECTED,
)
}
///|
pub fn bench_bytecode_env_access() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/env_access",
BYTECODE_ENV_ACCESS_SRC,
BYTECODE_MICRO_ACCESS_EXPECTED,
)
}
///|
pub fn bench_bytecode_captured_access() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/captured_access",
BYTECODE_CAPTURED_ACCESS_SRC,
BYTECODE_MICRO_ACCESS_EXPECTED,
)
}
///|
pub fn bench_bytecode_plain_call_control() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/plain_call_control",
BYTECODE_PLAIN_CALL_CONTROL_SRC,
BYTECODE_MICRO_CALL_EXPECTED,
)
}
///|
pub fn bench_bytecode_plain_call() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/plain_call",
BYTECODE_PLAIN_CALL_SRC,
BYTECODE_MICRO_CALL_EXPECTED,
)
}
///|
pub fn bench_bytecode_runtime_helpers() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/runtime_helpers",
BYTECODE_RUNTIME_HELPERS_SRC,
BYTECODE_MICRO_CALL_EXPECTED,
)
}
///|
fn bench_bytecode_property_get() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/property_get",
BYTECODE_PROPERTY_GET_SRC,
BYTECODE_MICRO_ACCESS_EXPECTED,
)
}
///|
fn bench_bytecode_property_set() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/property_set",
BYTECODE_PROPERTY_SET_SRC,
"99999",
)
}
///|
fn bench_bytecode_method_call() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/method_call",
BYTECODE_METHOD_CALL_SRC,
BYTECODE_MICRO_CALL_EXPECTED,
)
}
///|
fn bench_bytecode_object_literal() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/object_literal",
BYTECODE_OBJECT_LITERAL_SRC,
"50005000",
)
}
///|
fn bench_bytecode_array_literal() -> BenchResult raise {
bench_bytecode_micro(
"isolate/bytecode/array_literal",
BYTECODE_ARRAY_LITERAL_SRC,
"50015000",
)
}
///|
pub fn bench_for_of() -> BenchResult raise {
verify(FOR_OF_SRC, "499500")
run_bench(
"exec/for_of",
Component,
{ warmup: 3, iterations: 20, group_size: 3, },
fn() raise { let _ = @lib.run(FOR_OF_SRC) },
)
}
///|
pub fn bench_object_construction() -> BenchResult raise {
verify(OBJECT_CONSTRUCTION_SRC, "1000")
run_bench(
"exec/object_construction",
Component,
{ warmup: 3, iterations: 20, group_size: 3, },
fn() raise { let _ = @lib.run(OBJECT_CONSTRUCTION_SRC) },
)
}
///|
pub fn bench_string_ops() -> BenchResult raise {
verify(STRING_OPS_SRC, "600")
run_bench(
"exec/string_ops",
Component,
{ warmup: 3, iterations: 20, group_size: 5, },
fn() raise { let _ = @lib.run(STRING_OPS_SRC) },
)
}
///|
pub fn bench_pipeline_exec_lex() -> BenchResult raise {
verify(PIPELINE_EXEC_SRC, PIPELINE_EXEC_EXPECTED)
run_bench(
"pipeline/exec/lex",
Workflow,
{ warmup: 3, iterations: 30, group_size: 500, },
fn() raise { let _ = @lexer.tokenize(PIPELINE_EXEC_SRC) },
stage=Frontend,
)
}
///|
pub fn bench_pipeline_exec_parse() -> BenchResult raise {
verify(PIPELINE_EXEC_SRC, PIPELINE_EXEC_EXPECTED)
let tokens = @lexer.tokenize(PIPELINE_EXEC_SRC)
let _ = @parser.parse_tokens(tokens)
run_bench(
"pipeline/exec/parse",
Workflow,
{ warmup: 3, iterations: 40, group_size: 2000, },
fn() raise { let _ = @parser.parse_tokens(tokens) },
stage=Frontend,
)
}
///|
pub fn bench_pipeline_exec_evaluate() -> BenchResult raise {
verify(PIPELINE_EXEC_SRC, PIPELINE_EXEC_EXPECTED)
let prog = @parser.parse(PIPELINE_EXEC_SRC)
let precheck_interp = @interpreter.new_interpreter()
let got = precheck_interp.run(prog.stmts).to_string()
if got != PIPELINE_EXEC_EXPECTED {
abort(
"bench correctness check failed\n source: PIPELINE_EXEC_SRC\n expected: \{PIPELINE_EXEC_EXPECTED}\n got: \{got}",
)
}
let interp = @interpreter.new_interpreter()
run_bench(
"pipeline/exec/evaluate",
Workflow,
{ warmup: 2, iterations: 10, group_size: 1, },
fn() raise { let _ = interp.run(prog.stmts) },
)
}
///|
pub fn bench_pipeline_closure_legacy_evaluate() -> BenchResult raise {
verify(PIPELINE_EXEC_SRC, PIPELINE_EXEC_EXPECTED)
let prog = @parser.parse(PIPELINE_EXEC_SRC)
let compiled = @compiler.compile_script_to_closure(prog.stmts)
let precheck_interp = @interpreter.new_interpreter()
let got = compiled(precheck_interp).to_string()
if got != PIPELINE_EXEC_EXPECTED {
abort(
"bench correctness check failed\n source: PIPELINE_EXEC_SRC compiled\n expected: \{PIPELINE_EXEC_EXPECTED}\n got: \{got}",
)
}
let interp = @interpreter.new_interpreter()
run_bench(
"pipeline/closure_legacy/evaluate",
Workflow,
{ warmup: 3, iterations: 20, group_size: 5, },
fn() raise { let _ = compiled(interp) },
)
}
///|
pub fn bench_pipeline_bytecode_compile() -> BenchResult raise {
verify(PIPELINE_EXEC_SRC, PIPELINE_EXEC_EXPECTED)
let prog = @parser.parse(PIPELINE_EXEC_SRC)
let bytecode = @compiler.compile_script_to_bytecode(prog.stmts)
let got = bytecode.run(@interpreter.new_interpreter()).to_string()
if got != PIPELINE_EXEC_EXPECTED {
abort(
"bench correctness check failed\n source: PIPELINE_EXEC_SRC bytecode compile\n expected: \{PIPELINE_EXEC_EXPECTED}\n got: \{got}",
)
}
run_bench(
"pipeline/bytecode/compile",
Workflow,
{ warmup: 3, iterations: 30, group_size: 200, },
fn() raise { let _ = @compiler.compile_script_to_bytecode(prog.stmts) },
stage=Frontend,
)
}
///|
pub fn bench_pipeline_bytecode_evaluate() -> BenchResult raise {
verify(PIPELINE_EXEC_SRC, PIPELINE_EXEC_EXPECTED)
let prog = @parser.parse(PIPELINE_EXEC_SRC)
let bytecode = @compiler.compile_script_to_bytecode(prog.stmts)
let precheck_interp = @interpreter.new_interpreter()
let got = bytecode.run(precheck_interp).to_string()
if got != PIPELINE_EXEC_EXPECTED {
abort(
"bench correctness check failed\n source: PIPELINE_EXEC_SRC bytecode\n expected: \{PIPELINE_EXEC_EXPECTED}\n got: \{got}",
)
}
let interp = @interpreter.new_interpreter()
run_bench(
"pipeline/bytecode/evaluate",
Workflow,
{ warmup: 3, iterations: 20, group_size: 5, },
fn() raise { let _ = bytecode.run(interp) },
)
}
///|
pub fn bench_parse_heavy() -> BenchResult raise {
run_bench(
"pipeline/parse_heavy",
Workflow,
{ warmup: 3, iterations: 30, group_size: 50, },
fn() raise { let _ = @parser.parse(PARSER_HEAVY_SRC) },
stage=Frontend,
)
}
// ---------------------------------------------------------------------------
// Grouped runners (used by main.mbt)
// ---------------------------------------------------------------------------
///|
priv struct BenchmarkCase {
name : String
category : Category
stage : BenchStage
run : () -> BenchResult raise
}
///|
fn BenchmarkCase::BenchmarkCase(
name : String,
category : Category,
stage : BenchStage,
run : () -> BenchResult raise,
) -> BenchmarkCase {
{ name, category, stage, run, }
}
///|
fn all_benchmark_cases() -> Array[BenchmarkCase] {
[
BenchmarkCase("startup/tiny_program", Regression, Startup, () => {
bench_startup_tiny()
}),
BenchmarkCase("lexer/small", Regression, Frontend, () => bench_lexer_small()),
BenchmarkCase("lexer/large", Regression, Frontend, () => bench_lexer_large()),
BenchmarkCase("exec/fibonacci_30", Regression, Execution, () => {
bench_fibonacci()
}),
BenchmarkCase("exec/property_chain", Regression, Execution, () => {
bench_property_chain()
}),
BenchmarkCase("startup/phase/parse_tiny", Component, Frontend, () => {
bench_startup_parse_tiny()
}),
BenchmarkCase("startup/phase/new_interpreter", Component, Startup, () => {
bench_startup_new_interpreter()
}),
BenchmarkCase(
"startup/phase/execute_preparsed_tiny",
Component,
Execution,
() => bench_startup_execute_preparsed_tiny(),
),
BenchmarkCase("startup/phase/event_loop_drain_empty", Component, Startup, () => {
bench_startup_event_loop_drain_empty()
}),
BenchmarkCase(
"startup/phase/result_stringify_output",
Component,
Execution,
() => bench_startup_result_stringify_output(),
),
BenchmarkCase("exec/array_map_filter", Component, Execution, () => {
bench_array_map_filter()
}),
BenchmarkCase("exec/closure_factory", Component, Execution, () => {
bench_closure_factory()
}),
BenchmarkCase(
"baseline/closure_legacy/closure_factory",
Component,
Execution,
() => bench_closure_legacy_closure_factory(),
),
BenchmarkCase("baseline/bytecode/closure_factory", Component, Execution, () => {
bench_bytecode_closure_factory()
}),
BenchmarkCase("isolate/bytecode/dispatch_stack", Component, Execution, () => {
bench_bytecode_dispatch_stack()
}),
BenchmarkCase("isolate/bytecode/local_access", Component, Execution, () => {
bench_bytecode_local_access()
}),
BenchmarkCase("isolate/bytecode/env_access", Component, Execution, () => {
bench_bytecode_env_access()
}),
BenchmarkCase("isolate/bytecode/captured_access", Component, Execution, () => {
bench_bytecode_captured_access()
}),
BenchmarkCase("isolate/bytecode/plain_call_control", Component, Execution, () => {
bench_bytecode_plain_call_control()
}),
BenchmarkCase("isolate/bytecode/plain_call", Component, Execution, () => {
bench_bytecode_plain_call()
}),
BenchmarkCase("isolate/bytecode/runtime_helpers", Component, Execution, () => {
bench_bytecode_runtime_helpers()
}),
BenchmarkCase("isolate/bytecode/property_get", Component, Execution, () => {
bench_bytecode_property_get()
}),
BenchmarkCase("isolate/bytecode/property_set", Component, Execution, () => {
bench_bytecode_property_set()
}),
BenchmarkCase("isolate/bytecode/method_call", Component, Execution, () => {
bench_bytecode_method_call()
}),
BenchmarkCase("isolate/bytecode/object_literal", Component, Execution, () => {
bench_bytecode_object_literal()
}),
BenchmarkCase("isolate/bytecode/array_literal", Component, Execution, () => {
bench_bytecode_array_literal()
}),
BenchmarkCase("exec/for_of", Component, Execution, () => bench_for_of()),
BenchmarkCase("exec/arithmetic_loop", Component, Execution, () => {
bench_arithmetic_loop()
}),
BenchmarkCase("exec/object_construction", Component, Execution, () => {
bench_object_construction()
}),
BenchmarkCase("exec/string_ops", Component, Execution, () => {
bench_string_ops()
}),
BenchmarkCase("regexp/retained_matcher", Component, Execution, () => {
bench_regexp_retained_matcher()
}),
BenchmarkCase("pipeline/exec/lex", Workflow, Frontend, () => {
bench_pipeline_exec_lex()
}),
BenchmarkCase("pipeline/exec/parse", Workflow, Frontend, () => {
bench_pipeline_exec_parse()
}),
BenchmarkCase("pipeline/exec/evaluate", Workflow, Execution, () => {
bench_pipeline_exec_evaluate()
}),
BenchmarkCase("pipeline/closure_legacy/evaluate", Workflow, Execution, () => {
bench_pipeline_closure_legacy_evaluate()
}),
BenchmarkCase("pipeline/bytecode/compile", Workflow, Frontend, () => {
bench_pipeline_bytecode_compile()
}),
BenchmarkCase("pipeline/bytecode/evaluate", Workflow, Execution, () => {
bench_pipeline_bytecode_evaluate()
}),
BenchmarkCase("pipeline/parse_heavy", Workflow, Frontend, () => {
bench_parse_heavy()
}),
]
}
///|
fn run_benchmark_cases(
cases : Array[BenchmarkCase],
) -> Array[BenchResult] raise {
let results : Array[BenchResult] = []
for benchmark in cases {
results.push((benchmark.run)())
}
results
}
///|
fn select_benchmark_cases(
requested : Array[String],
) -> Array[BenchmarkCase] raise {
let cases = all_benchmark_cases()
let known : Map[String, Bool] = Map([])
for benchmark in cases {
known[benchmark.name] = true
}
let selected : Map[String, Bool] = Map([])
for name in requested {
guard known.contains(name) else { fail("unknown benchmark row: " + name) }
selected[name] = true
}
cases.filter(benchmark => selected.contains(benchmark.name))
}
///|
fn run_category(category : Category) -> Array[BenchResult] raise {
run_benchmark_cases(
all_benchmark_cases().filter(benchmark => {
benchmark.category.label() == category.label()
}),
)
}
///|
pub fn run_regression() -> Array[BenchResult] raise {
run_category(Regression)
}
///|
fn run_startup_phase_components() -> Array[BenchResult] raise {
[
bench_startup_parse_tiny(),
bench_startup_new_interpreter(),
bench_startup_execute_preparsed_tiny(),
bench_startup_event_loop_drain_empty(),
bench_startup_result_stringify_output(),
]
}
///|
pub fn run_startup_phases() -> Array[BenchResult] raise {
let out : Array[BenchResult] = [bench_startup_tiny()]
for r in run_startup_phase_components() {
out.push(r)
}
out
}
///|
pub fn run_component() -> Array[BenchResult] raise {
run_category(Component)
}
///|
pub fn run_workflow() -> Array[BenchResult] raise {
run_category(Workflow)
}
///|
pub fn run_all() -> Array[BenchResult] raise {
run_benchmark_cases(all_benchmark_cases())
}
///|
/// Stable list of all benchmark names, in canonical run order.
/// Used by main.mbt to print --list output.
pub fn all_bench_names() -> Array[(String, String, String)] {
all_benchmark_cases().map(benchmark => {
(benchmark.name, benchmark.category.label(), benchmark.stage.label())
})
}