code wiki / _hdl_build / nx_osbench_kern.nx
nx_osbench_kern.nx source
↩ module page · 205 lines · 10246 B
1// nx_osbench_kern.nx -- rung F853b (lane osbench): the KERNEL-AXIS harness.
2//
3// WHY THIS EXISTS: the operator mission is RAW KERNEL PERFORMANCE, and 750 of 1000 permille of that
4// mission (syscall_trap, ipc, thread_spawn, context_switch) was UNMEASURED -- we did not even know
5// what LINUX costs on this hardware, so we had no target to aim at. This organ measures the LINUX
6// side of the kernel axes so the number NishiOS must beat is on record.
7//
8// ★ HONEST SCOPE, STATED UP FRONT: these are REFERENCE rows, not comparisons. NishiOS does not run
9// as an OS on this substrate -- it is hosted, so it has no syscall-trap or scheduler of its own
10// here. There is therefore NO NishiOS counterpart to pair against, and the judge scores NOTHING
11// from this file. Emitting a one-sided number as if it were a head-to-head would be exactly the
12// no-wave violation this lane exists to prevent. The NishiOS halves stay UNMEASURED, with the
13// rung that unblocks them named (F856 bare-metal node).
14//
15// ★ A STRUCTURAL NOTE THAT MUST NOT BE SCORED AS A WIN: NishiOS's native contract has no syscall
16// trap on the store path at all (capability call, not a ring transition). That is a FLOOR/design
17// difference, and the gap ledger's rule applies -- "we own it" is never printed as "we beat it".
18// It is recorded as prose here, never as a ratio.
19//
20// AXES (Linux, this host):
21// syscall_trap -- minimal round trip into the kernel and back (close on an invalid fd:
22// a real trap, EBADF immediately, near-zero kernel work = trap floor)
23// pipe_write_read -- a byte through a real pipe buffer, same process. NAMED HONESTLY: this is
24// the pipe-buffer cost, NOT an inter-process IPC round trip and NOT a context
25// switch. Calling it ipc_roundtrip would be a lie by label.
26// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
27import "nx_syscalls.nx"
28import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
29
30const OK_N: i64 = 2000
31const OK_ROUNDS: i64 = 15
32const OK_WARM: i64 = 200
33const OK_MODE: i64 = 420
34const OK_NSEC: i64 = 1000000000
35const OK_BADFD: i64 = 0 - 1
36const OK_UNSTABLE: i64 = 100
37
38func ok_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
39func ok_w(fd: i64, s: *u8) -> i64 { let n: i64 = ok_len(s); sys_write(fd, s, n); return 0 }
40func ok_p(s: *u8) -> i64 { return ok_w(1, s) }
41// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
42// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
43// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
44// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
45func ok_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
46func ok_pn(v: i64) -> i64 { return ok_wn(1, v) }
47
48func ok_ns(ts: *i64) -> i64 {
49 sys_clock_gettime_mono(ts)
50 let s: i64 = ts[0]
51 let n: i64 = ts[1]
52 return s * OK_NSEC + n
53}
54
55// sort a copy, return rank r. FLAG LOOP -- a pseudo-break assigning the loop var destroys the
56// insertion index and silently shuffles instead of sorting (that defect produced a NEGATIVE IQR
57// in the sibling harness and passed a naive gate as a false GREEN).
58func ok_rank(arr: *i64, n: i64, r: i64) -> i64 {
59 let c: *i64 = sys_mmap(n * 8 + 8) as *i64
60 var i: i64 = 0
61 while i < n { c[i] = arr[i]; i = i + 1 }
62 var a: i64 = 1
63 while a < n {
64 let key: i64 = c[a]
65 var b: i64 = a - 1
66 var placed: i64 = 0
67 while placed == 0 {
68 if b < 0 { placed = 1 } else {
69 let cb: i64 = c[b]
70 if cb > key { c[b+1] = cb; b = b - 1 } else { placed = 1 }
71 }
72 }
73 c[b+1] = key
74 a = a + 1
75 }
76 return c[r]
77}
78func ok_med(arr: *i64, n: i64) -> i64 { return ok_rank(arr, n, n/2) }
79func ok_iqr(arr: *i64, n: i64) -> i64 {
80 let m: i64 = ok_med(arr, n)
81 if m <= 0 { return 0 }
82 let q1: i64 = ok_rank(arr, n, n/4)
83 let q3: i64 = ok_rank(arr, n, (n*3)/4)
84 return ((q3 - q1) * 1000) / m
85}
86func ok_rng(arr: *i64, n: i64) -> i64 {
87 var lo: i64 = arr[0]
88 var hi: i64 = arr[0]
89 var i: i64 = 0
90 while i < n {
91 let v: i64 = arr[i]
92 if v < lo { lo = v }
93 if v > hi { hi = v }
94 i = i + 1
95 }
96 let m: i64 = ok_med(arr, n)
97 if m <= 0 { return 0 }
98 return ((hi - lo) * 1000) / m
99}
100
101// axis 0 = syscall trap floor, axis 1 = pipe write+read. Returns ns/op for one round.
102func ok_round(axis: i64, rfd: i64, wfd: i64) -> i64 {
103 let ts: *i64 = sys_mmap(32) as *i64
104 let b: *u8 = sys_mmap(16)
105 b[0] = 65 as u8
106 var w: i64 = 0
107 while w < OK_WARM {
108 if axis == 0 { sys_close(OK_BADFD) }
109 if axis == 1 { sys_write(wfd, b, 1); sys_read(rfd, b, 1) }
110 w = w + 1
111 }
112 let t0: i64 = ok_ns(ts)
113 var i: i64 = 0
114 while i < OK_N {
115 if axis == 0 { sys_close(OK_BADFD) }
116 if axis == 1 { sys_write(wfd, b, 1); sys_read(rfd, b, 1) }
117 i = i + 1
118 }
119 let t1: i64 = ok_ns(ts)
120 let d: i64 = t1 - t0
121 if d < 0 { return 0 }
122 return d / OK_N
123}
124
125func ok_axname(axis: i64) -> *u8 {
126 if axis == 0 { return "syscall_trap" as *u8 }
127 return "pipe_write_read" as *u8
128}
129
130func main() -> i64 {
131 ok_p("nx_osbench_kern -- LINUX kernel-axis REFERENCE numbers (the target NishiOS must beat)\n" as *u8)
132 ok_p(" These are ONE-SIDED reference rows. NishiOS is HOSTED on this substrate: it has no syscall\n" as *u8)
133 ok_p(" trap and no scheduler of its own here, so there is NO counterpart to pair against and the\n" as *u8)
134 ok_p(" judge scores NOTHING from this file. A one-sided number presented as a head-to-head would\n" as *u8)
135 ok_p(" be the exact no-wave violation this lane exists to prevent.\n\n" as *u8)
136
137 // a real pipe for axis 1.
138 // ⚠WIDTH TRAP (cost a hang): sys_pipe2 is declared `(fds: *i64, flags)` but the KERNEL writes
139 // `int pipefd[2]` = TWO 32-BIT ints into that buffer. Reading it as *i64 packs BOTH fds into
140 // slot 0 and leaves slot 1 as GARBAGE -- sys_read on that garbage fd blocks forever (the run
141 // hung after emitting the syscall_trap row). The pointer TYPE on the wrapper invites this bug.
142 // Read the buffer as *i32: [0]=read end, [1]=write end.
143 let pmem: *u8 = sys_mmap(32)
144 let prc: i64 = sys_pipe2(pmem as *i64, 0)
145 let pf32: *i32 = pmem as *i32
146 var rfd: i64 = 0 - 1
147 var wfd: i64 = 0 - 1
148 if prc == 0 { rfd = pf32[0] as i64; wfd = pf32[1] as i64 }
149 if prc != 0 { ok_p(" WARN pipe2 failed -- pipe_write_read will be SKIPPED, not faked\n" as *u8) }
150 ok_p(" pipe fds: r="); ok_pn(rfd); ok_p(" w="); ok_pn(wfd); ok_p("\n" as *u8)
151
152 let fd: i64 = sys_openat_append("knowledge/status/osbench_measured.dat" as *u8, OK_MODE)
153 if fd < 0 { ok_p("KERN-FAIL cannot open dat\n" as *u8); sys_exit(1); return 1 }
154 ok_w(fd, "# osbench_kern run (LINUX reference only; no NishiOS counterpart on this substrate)\n" as *u8)
155
156 ok_p(" AXIS ns/op(med) IQR range stability\n" as *u8)
157 let samp: *i64 = sys_mmap(OK_ROUNDS * 8 + 8) as *i64
158 var axis: i64 = 0
159 while axis < 2 {
160 var skip: i64 = 0
161 if axis == 1 { if prc != 0 { skip = 1 } }
162 if axis == 1 { if rfd < 0 { skip = 1 } }
163 if axis == 1 { if wfd < 0 { skip = 1 } }
164 if skip == 0 {
165 var r: i64 = 0
166 while r < OK_ROUNDS { samp[r] = ok_round(axis, rfd, wfd); r = r + 1 }
167 let med: i64 = ok_med(samp, OK_ROUNDS)
168 let iqr: i64 = ok_iqr(samp, OK_ROUNDS)
169 let rng: i64 = ok_rng(samp, OK_ROUNDS)
170 ok_p(" "); ok_p(ok_axname(axis))
171 ok_p(" "); ok_pn(med)
172 ok_p(" "); ok_pn(iqr)
173 ok_p(" "); ok_pn(rng)
174 if iqr > OK_UNSTABLE { ok_p(" UNSTABLE\n" as *u8) } else { ok_p(" stable\n" as *u8) }
175 ok_w(fd, "REFERENCE\t" as *u8); ok_w(fd, ok_axname(axis))
176 ok_w(fd, "\tlinux-host\tnative\t" as *u8); ok_wn(fd, med)
177 ok_w(fd, "\t" as *u8); ok_wn(fd, iqr)
178 ok_w(fd, "\tone-sided linux reference; no NishiOS counterpart on a hosted substrate\n" as *u8)
179 }
180 axis = axis + 1
181 }
182
183 // The NishiOS halves stay explicitly UNMEASURED with the unblocking rung named.
184 ok_w(fd, "UNMEASURED\tsyscall_trap\tnishios\t-1\t-1\tNishiOS is hosted here; native contract has NO trap on the store path (FLOOR/design, never scored) - real number needs F856\n" as *u8)
185 ok_w(fd, "UNMEASURED\tipc_roundtrip\tnishios\t-1\t-1\tneeds NishiOS running AS an OS - F856\n" as *u8)
186 ok_w(fd, "UNMEASURED\tthread_spawn\tnishios\t-1\t-1\tneeds NishiOS running AS an OS - F856\n" as *u8)
187 ok_w(fd, "UNMEASURED\tcontext_switch\tnishios\t-1\t-1\tneeds NishiOS running AS an OS - F856\n" as *u8)
188 sys_close(fd)
189
190 ok_p("\n DECLARED ENVELOPE: N="); ok_pn(OK_N)
191 ok_p(" ops/round, rounds="); ok_pn(OK_ROUNDS)
192 ok_p(", single-threaded, single-node, warm.\n" as *u8)
193 ok_p(" syscall_trap = close(-1): a REAL trap returning EBADF with near-zero kernel work = the trap FLOOR.\n" as *u8)
194 ok_p(" pipe_write_read = one byte through a real pipe buffer, SAME process. Named honestly: this is\n" as *u8)
195 ok_p(" the pipe-buffer cost, NOT an inter-process IPC round trip and NOT a context switch. Labelling\n" as *u8)
196 ok_p(" it ipc_roundtrip would be a lie by label -- those axes remain UNMEASURED, gated on F856.\n" as *u8)
197 ok_p("\n STRUCTURAL (recorded as prose, NEVER as a ratio): the NishiOS native contract performs store\n" as *u8)
198 ok_p(" access via a capability call with NO ring transition, so the trap cost above has no NishiOS\n" as *u8)
199 ok_p(" analogue at all. Per the gap-ledger rule, 'we own it' is never printed as 'we beat it'.\n" as *u8)
200
201 let lg: i64 = sys_openat_append("knowledge/status/osbench_kern.log" as *u8, OK_MODE)
202 if lg >= 0 { ok_w(lg, "NX-OSBENCH-KERN verdict=GREEN linux reference axes emitted; nishios halves UNMEASURED (F856)\n" as *u8); sys_close(lg) }
203 ok_p("\nNX-OSBENCH-KERN verdict=GREEN (linux reference emitted; nothing scored, nothing claimed)\n" as *u8)
204 return 0
205}