code wiki / (root) / nx_bench_companion_timed.nx

nx_bench_companion_timed.nx source

↩ module page · 107 lines · 3781 B

1// nx_bench_companion_timed.nx -- wall-clock-wrapped substrate measurement. 2// 3// Sibling to [[nx_bench_companion]]. Adds REAL wall-clock timing 4// (via nx_clock_monotonic_ns) around bench capture, so substrate 5// counters AND elapsed microseconds land in one report. 6// 7// Per CARDINAL [[feedback-no-strawman-perf-comparisons]]: wall-clock 8// under qemu-riscv64 is NOT comparable to wall-clock on physical 9// hardware (qemu is single-threaded + interpreter-emulated). What it 10// IS: the substrate's first real time-measurement primitive, so 11// future physical-hardware bench runs use the same call. When the 12// Phase E + physical-board arcs land, this primitive doesn't change; 13// only the wall-clock number does. 14 15import "nx_syscalls.nx" 16import "nx_tier.nx" 17import "nx_clock.nx" 18import "nx_session.nx" 19import "nx_bench_companion.nx" 20 21// ===== Sealed verdict =========================================== 22 23const NX_BCTM_OK: nx_int = 0 24const NX_BCTM_NULL_SESSION: nx_int = 1 25const NX_BCTM_NULL_REPORT: nx_int = 2 26const NX_BCTM_NEGATIVE_ELAPSED: nx_int = 3 27const NX_BCTM_INVALID: nx_int = 4 28const NX_BCTM_N: nx_int = 5 29 30func nx_bctm_v_is_valid(v: nx_int) -> nx_int { 31 if v < 0 { return 0 } 32 if v >= NX_BCTM_N { return 0 } 33 return 1 34} 35 36// ===== Struct: NxBenchTimedReport =============================== 37// 38// Wraps an NxBenchReport with the wall-clock measurement. 39 40struct NxBenchTimedReport { 41 base: *NxBenchReport, 42 wallclock_start_ns: i64, 43 wallclock_end_ns: i64, 44 wallclock_elapsed_us: i64, 45 verdict: nx_int, 46} 47 48const NX_BCTM_BYTES: nx_int = 40 49 50func nx_bctm_new(base: *NxBenchReport) -> *NxBenchTimedReport { 51 if (base as i64) == 0 { return 0 as *NxBenchTimedReport } 52 let raw: *u8 = sys_mmap(NX_BCTM_BYTES) 53 let t: *NxBenchTimedReport = raw as *NxBenchTimedReport 54 t.base = base 55 t.wallclock_start_ns = 0 56 t.wallclock_end_ns = 0 57 t.wallclock_elapsed_us = 0 58 t.verdict = NX_BCTM_OK 59 return t 60} 61 62// ===== Timed capture ============================================ 63// 64// Reads wall-clock NOW, captures session counters, computes elapsed 65// from caller-provided start. Calling pattern: 66// 67// let t: *NxBenchTimedReport = nx_bctm_new(report) 68// t.wallclock_start_ns = nx_clock_monotonic_ns() 69// ... drive workload ... 70// nx_bctm_capture_finish(t, session, n_kinds) 71// 72// After capture_finish: t.wallclock_elapsed_us holds delta in us. 73 74func nx_bctm_capture_finish(t: *NxBenchTimedReport, 75 s: *NxSession, 76 n_subscription_kinds_to_count: nx_int) -> nx_int { 77 if (t as i64) == 0 { return NX_BCTM_INVALID } 78 if (s as i64) == 0 { return NX_BCTM_NULL_SESSION } 79 if (t.base as i64) == 0 { return NX_BCTM_NULL_REPORT } 80 let end_ns: i64 = nx_clock_monotonic_ns() 81 t.wallclock_end_ns = end_ns 82 let elapsed_ns: i64 = end_ns - t.wallclock_start_ns 83 if elapsed_ns < 0 { 84 t.verdict = NX_BCTM_NEGATIVE_ELAPSED 85 return NX_BCTM_NEGATIVE_ELAPSED 86 } 87 t.wallclock_elapsed_us = elapsed_ns / 1000 88 let v_cap: nx_int = nx_bc_capture(s, t.base, n_subscription_kinds_to_count, end_ns as nx_size) 89 if v_cap != NX_BC_V_OK { 90 t.verdict = NX_BCTM_INVALID 91 return NX_BCTM_INVALID 92 } 93 t.verdict = NX_BCTM_OK 94 return NX_BCTM_OK 95} 96 97// ===== Accessors ================================================ 98 99func nx_bctm_elapsed_us(t: *NxBenchTimedReport) -> i64 { 100 if (t as i64) == 0 { return 0 - 1 } 101 return t.wallclock_elapsed_us 102} 103 104func nx_bctm_verdict(t: *NxBenchTimedReport) -> nx_int { 105 if (t as i64) == 0 { return NX_BCTM_INVALID } 106 return t.verdict 107}