//! VM-Durchsatz-Benchmark (Messlatte docs/tbvm-design.md, „Performance"):
//! Schleifen- und String-Lasten. Eigener Harness; `cargo bench -p tb-vm`.

use std::time::Instant;
use tb_runtime::host::CaptureHost;
use tb_vm::interp::{RunEvent, Vm};

fn run_timed(name: &str, src: &str, work_units: f64, unit: &str) {
    let module = tb_vm::compile_source("BENCH", src).expect("kompiliert");
    let mut vm = Vm::new(module);
    let mut host = CaptureHost::default();
    let t = Instant::now();
    let ev = vm.run(&mut host);
    let secs = t.elapsed().as_secs_f64();
    assert_eq!(ev, RunEvent::Ended, "{ev:?}");
    println!(
        "  {name}: {:.0} ms  ({:.1} Mio {unit}/s)",
        secs * 1000.0,
        work_units / secs / 1e6
    );
}

fn main() {
    println!("VM-Durchsatz-Benchmark (Release):");

    // Ganzzahl-Schleife: 10 Mio Iterationen mit Arithmetik.
    run_timed(
        "INTEGER-Schleife (10 Mio)",
        "s& = 0\nFOR i& = 1 TO 10000000\ns& = (s& + i& MOD 7) MOD 100000\nNEXT\nPRINT s&",
        10_000_000.0,
        "Iterationen",
    );

    // Gleitkomma-Schleife.
    run_timed(
        "DOUBLE-Schleife (5 Mio)",
        "d# = 0\nFOR i& = 1 TO 5000000\nd# = d# + i& * 1.000001\nNEXT\nPRINT CINT(d# / 1000000000000#)",
        5_000_000.0,
        "Iterationen",
    );

    // Prozeduraufrufe.
    run_timed(
        "SUB-Aufrufe (1 Mio, BYREF)",
        "SUB Inc (x&)\nx& = x& + 1\nEND SUB\nn& = 0\nFOR i& = 1 TO 1000000\nInc n&\nNEXT\nPRINT n&",
        1_000_000.0,
        "Aufrufe",
    );

    // String-Last: MID$/INSTR/Verkettung.
    run_timed(
        "String-Funktionen (200k)",
        "s$ = \"Terminal Basic Benchmark\"\nn& = 0\nFOR i& = 1 TO 200000\nt$ = MID$(s$, (i& MOD 10) + 1, 8) + \"x\"\nn& = n& + INSTR(t$, \"a\") + LEN(t$)\nNEXT\nPRINT n& > 0",
        200_000.0,
        "Runden",
    );
}
