// Benchmarks for Runs operations
// Run with: moon bench --release
// BenchRun: a non-mergeable run type for benchmarks.
// can_merge returns false so runs stay separate after construction,
// giving realistic multi-run data for range/concat/extend benchmarks.
// No derive(Debug, Eq) — avoids leaking into the public interface.
///|
priv struct BenchRun {
len : Int
}
///|
impl HasLength for BenchRun with fn length(self : BenchRun) -> Int {
self.len
}
///|
impl Spanning for BenchRun with fn span(self : BenchRun) -> Int {
self.len
}
///|
impl Mergeable for BenchRun with fn can_merge(_a : BenchRun, _b : BenchRun) -> Bool {
false
}
///|
impl Mergeable for BenchRun with fn merge(a : BenchRun, _b : BenchRun) -> BenchRun {
a // unreachable since can_merge is false
}
///|
fn make_bench_runs(count : Int, run_len : Int) -> Runs[BenchRun] {
let arr : Array[BenchRun] = []
for _i = 0; _i < count; _i = _i + 1 {
arr.push({ len: run_len })
}
Runs::from_array(arr)
}
///|
/// Benchmark: range with small span near start
test "runs - range iter (small)" (b : @bench.T) {
let runs = make_bench_runs(10000, 4)
let start = 0
let end = 400
b.bench(fn() {
let it = match runs.range(start~, end~) {
Ok(it) => it
Err(_) => abort("range failed")
}
b.keep(it.count())
})
}
///|
/// Benchmark: range with span near middle
test "runs - range iter (middle)" (b : @bench.T) {
let runs = make_bench_runs(10000, 4)
let total = 10000 * 4
let start = total / 2
let end = start + 400
b.bench(fn() {
let it = match runs.range(start~, end~) {
Ok(it) => it
Err(_) => abort("range failed")
}
b.keep(it.count())
})
}
///|
/// Benchmark: batch concat of non-mergeable runs
test "runs - concat batch" (b : @bench.T) {
let runs_a = make_bench_runs(500, 10)
let runs_b = make_bench_runs(500, 10)
b.bench(fn() {
let result = runs_a.concat(runs_b)
b.keep(result.length())
})
}
///|
/// Benchmark: batch extend of non-mergeable runs
test "runs - extend batch" (b : @bench.T) {
let template = make_bench_runs(500, 10)
let runs_b = make_bench_runs(500, 10)
b.bench(fn() {
let runs_a = Runs(template.0.copy())
runs_a.extend(runs_b)
b.keep(runs_a.length())
})
}
///|
/// Benchmark: from_array_batch construction (strings merge into one run)
test "runs - from_array_batch" (b : @bench.T) {
let arr : Array[String] = []
for i = 0; i < 1000; i = i + 1 {
arr.push("x")
}
b.bench(fn() {
let runs = Runs::from_array_batch(arr)
b.keep(runs.length())
})
}