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}