code wiki / (root) / nx_native_micro_bench.nx

nx_native_micro_bench.nx source

↩ module page · 63 lines · 2104 B

1// nx_native_micro_bench.nx -- minimal NATIVE x86_64 Nishi micro-bench. 2// 3// Goal: measure a tight integer-loop workload running NATIVE x86_64 4// (no qemu), output the wall-clock to stdout, return exit-code = 0. 5// 6// Apples-to-apples comparator vs the equivalent C loop run on the 7// same hardware. Surfaces the substrate's REAL per-op cost when 8// freed from the qemu interpreter (~100-1000x overhead). 9// 10// Workload: sum integers 0..N-1 with a register-only loop. Trivial 11// math; the comparison is "how fast can Nishi emit tight loops on 12// x86_64 vs gcc -O2 on the same loop." 13 14// (nx_syscalls_x86_64.nx import REMOVED 2026-07-31, debt 1785528831: this file already 15// gets the canonical syscall layer via nx_clock.nx -> syscalls.nx, so importing the raw-x86 16// module too put TWO syscall layers in one TU -- every wrapper twice, numbering picked by 17// definition ORDER, silently.) 18import "nx_clock.nx" 19 20func _emit_dec_i64(fd: i64, n: i64) -> i64 { 21 let scratch: *u8 = sys_mmap(32) 22 var v: i64 = n 23 var neg: nx_int = 0 24 if v < 0 { neg = 1; v = 0 - v } 25 var k: i64 = 0 26 if v == 0 { scratch[0] = 0x30 as u8; k = 1 } 27 while v > 0 { 28 scratch[k] = (0x30 + (v - (v / 10) * 10)) as u8 29 v = v / 10 30 k = k + 1 31 } 32 let rev: *u8 = sys_mmap(48) 33 var ro: i64 = 0 34 if neg == 1 { rev[0] = 0x2D as u8; ro = 1 } 35 var j: i64 = 0 36 while j < k { rev[ro + j] = scratch[k - 1 - j]; j = j + 1 } 37 rev[ro + k] = 0x0A as u8 38 sys_write(fd, rev, ro + k + 1) 39 return 0 40} 41 42func main() -> i64 { 43 let N: i64 = 100000000 // 100 million iterations 44 45 let start: i64 = nx_clock_monotonic_ns() 46 47 // Tight sum loop -- gcc -O2 would auto-vectorize this; nxc2's 48 // codegen is a fair comparison even unoptimized. 49 var sum: i64 = 0 50 var i: i64 = 0 51 while i < N { 52 sum = sum + i 53 i = i + 1 54 } 55 56 let end: i64 = nx_clock_monotonic_ns() 57 let elapsed_us: i64 = (end - start) / 1000 58 59 _emit_dec_i64(1, sum) // print sum (sanity check) 60 _emit_dec_i64(1, elapsed_us) // print wall-clock microseconds 61 62 return 0 63}