code wiki / _hdl_build / nx_bench_vs_c.nx
nx_bench_vs_c.nx source
↩ module page · 78 lines · 4310 B
1// nx_bench_vs_c.nx -- HORIZONTAL benchmark organ (Referee/Engineer-owned): races the sovereign
2// toolchain against the C toolchain (gcc) on the SAME .s artifact -- the operator-sanctioned use
3// of C ("benchmarking only"). For argv[1]=<name> (expects /tmp/<name>.s from nx_sov_build_run):
4// lane A: nxasm_x86_main .s -> ELF (ours) timed ms
5// lane B: gcc -nostdlib .s -> ELF (C oracle) timed ms
6// then RUNS both ELFs and compares exit codes (differential correctness, csmith-lite).
7// Emits one parseable line appended to /tmp/nishi_ladder.log for the wiki ladder:
8// BENCH name= sov_ms= gcc_ms= sov_exit= gcc_exit= agree=
9// license_tier: ORIGINAL (fork/exec spine reused from nx_sov_build_run)
10import "nx_syscalls.nx"
11import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
12
13func bv_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
14// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
15// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
16// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
17// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
18func bv_n(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
19func bv_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off+i]=s[i];i=i+1} return off+i }
20
21func bv_run(path: *u8, argv: *i64, envp: *i64) -> i64 {
22 let pid: i64 = sys_fork()
23 if pid == 0 { sys_execve(path, argv, envp); sys_exit(127) }
24 let st: *i64 = sys_mmap(16) as *i64
25 sys_wait4(pid, st, 0)
26 let sig: i64 = st[0] & 0x7f
27 if sig != 0 { return 128 + sig }
28 return (st[0] >> 8) & 0xff
29}
30
31func main(argc: i64, argv: *i64) -> i64 {
32 if argc < 2 { bv_w(1, "usage: nx_bench_vs_c <name> (needs /tmp/<name>.s)\n" as *u8); sys_exit(2); return 2 }
33 let name: *u8 = argv[1] as *u8
34 let envp: *i64 = sys_mmap(32) as *i64
35 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
36 let sp: *u8 = sys_mmap(256); var o: i64 = bv_cat(sp,0,"/tmp/" as *u8); o=bv_cat(sp,o,name); o=bv_cat(sp,o,".s" as *u8); sp[o]=0 as u8
37 let ea: *u8 = sys_mmap(256); o = bv_cat(ea,0,"/tmp/" as *u8); o=bv_cat(ea,o,name); o=bv_cat(ea,o,".bvA.elf" as *u8); ea[o]=0 as u8
38 let eb: *u8 = sys_mmap(256); o = bv_cat(eb,0,"/tmp/" as *u8); o=bv_cat(eb,o,name); o=bv_cat(eb,o,".bvB.elf" as *u8); eb[o]=0 as u8
39
40 // lane A: sovereign assembler
41 let t0: i64 = sys_now_ms()
42 let aa: *i64 = sys_mmap(40) as *i64
43 aa[0] = "_offc/nxasm_x86_main.elf" as *u8 as i64; aa[1] = sp as i64; aa[2] = ea as i64; aa[3] = 0
44 let rca: i64 = bv_run("_offc/nxasm_x86_main.elf" as *u8, aa, envp)
45 let sov_ms: i64 = sys_now_ms() - t0
46 // lane B: the C toolchain (gcc as assembler+linker), the sanctioned oracle
47 let t1: i64 = sys_now_ms()
48 let bb: *i64 = sys_mmap(80) as *i64
49 bb[0] = "/usr/bin/gcc" as *u8 as i64; bb[1] = "-nostdlib" as *u8 as i64; bb[2] = "-no-pie" as *u8 as i64
50 bb[3] = "-static" as *u8 as i64; bb[4] = sp as i64; bb[5] = "-o" as *u8 as i64; bb[6] = eb as i64; bb[7] = 0
51 let rcb: i64 = bv_run("/usr/bin/gcc" as *u8, bb, envp)
52 let gcc_ms: i64 = sys_now_ms() - t1
53
54 // differential run (only if both built)
55 var e1: i64 = 0 - 1
56 var e2: i64 = 0 - 2
57 if rca == 0 { let ra: *i64 = sys_mmap(16) as *i64; ra[0]=ea as i64; ra[1]=0; e1 = bv_run(ea, ra, envp) }
58 if rcb == 0 { let rb: *i64 = sys_mmap(16) as *i64; rb[0]=eb as i64; rb[1]=0; e2 = bv_run(eb, rb, envp) }
59 var agree: i64 = 0
60 if e1 == e2 { agree = 1 }
61
62 let lfd: i64 = sys_openat_append("/tmp/nishi_ladder.log" as *u8, 0x1a4)
63 var f: i64 = 1
64 while f >= 0 {
65 let fd: i64 = lfd * f + 1 * (1 - f) // f=1 -> ladder log, f=0 -> stdout
66 bv_w(fd, "BENCH name=" as *u8); bv_w(fd, name)
67 bv_w(fd, " sov_ms=" as *u8); bv_n(fd, sov_ms)
68 bv_w(fd, " gcc_ms=" as *u8); bv_n(fd, gcc_ms)
69 bv_w(fd, " sov_exit=" as *u8); bv_n(fd, e1)
70 bv_w(fd, " gcc_exit=" as *u8); bv_n(fd, e2)
71 bv_w(fd, " agree=" as *u8); bv_n(fd, agree)
72 bv_w(fd, "\n" as *u8)
73 f = f - 1
74 }
75 sys_close(lfd)
76 if agree == 0 { sys_exit(1); return 1 }
77 sys_exit(0); return 0
78}