- Sema zum Lowering-Pass umgebaut: typisiertes HIR (Slots, explizite Konvertierungsknoten) als Codegen-Eingabe; BYREF verlangt exakten Typ - Bytecode-Feindesign umgesetzt: monomorpher Opcode-Satz, .tbc-Container (Formatversion 1) mit eigenem Writer/Reader - Codegenerator HIR -> Bytecode (Fixup-Listen, keine globalen Passes) - TBVM-Interpreter: Kontrollfluss, GOSUB-Stack je Frame, BYREF/BYVAL, STATIC, DEF FN, DATA/READ/RESTORE, ON [LOCAL] ERROR/RESUME/ERR/ERL, Breakpoints/Einzelschritt/Inspektion, STOP fortsetzbar - Runtime-Scheibe: Host-Trait (Konsole/Capture), Builtin-Tabelle, Konvertierungsmatrix, PRINT-Formatierung/Druckzonen, Stringfunktionen - tbc run/build/check mit Exit-Codes nach Entscheidung D6 - Korpus-Harness (byte-genauer Vergleich) + 3 neue Korpusdateien (konvertierung, fehlerbehandlung, byref); 137 Tests gruen - Benchmarks: Einzelmodul 1,2 ms / Projekt 49.760 Zeilen 124 ms (Budgets eingehalten), VM ~5 Mio Schleifeniterationen/s - Doku fortgeschrieben (tbvm-design, sprachreferenz, PLAN); verlagerte Punkte als explizite Aufgaben in Phase 3 - OpenSpec-Change phase-2-bytecode-vm (27/27 Tasks) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
58 lines
1.8 KiB
Rust
58 lines
1.8 KiB
Rust
//! 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",
|
|
);
|
|
}
|