code wiki / _hdl_build / nx_room_perf_gate.nx

nx_room_perf_gate.nx source

↩ module page · 385 lines · 15706 B

1import "nx_gate_base.nx" 2import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 3// nx_room_perf_gate.nx -- ENGINEER perf gate: MEASURE the live room, then gate it. 4// 5// Operator 2026-06-10: "we tested the platform and now we can all join but the 6// performance was poor." Optimal/S-class doctrine: slow is a bug, and a bug 7// needs a MEASURED, re-runnable gate before any fix. This gate runs the same 8// sovereign TLS clients as nx_room_live_gate against the PUBLIC stack and 9// measures what the user feels: 10// P1 unloaded latency -- A sends paced 64B timestamped frames; B reports 11// inter-client delivery latency (same-process clock, 12// so the numbers are exact) p50/max in usec 13// P2 loaded throughput -- a forked sender child streams 120 x 8KB timestamped 14// frames from A; the parent reads them at BOTH B and C; 15// delivered count, wall time, KB/s, loaded p50/max 16// P4 slow-reader stall -- C STOPS reading entirely; a child streams 96 x 8KB 17// from A; B must STILL receive all 96. On the v2 18// relay (blocking serial broadcast) one slow peer 19// wedges the whole daemon -> this is the measured 20// root cause of "poor performance", RED until fixed. 21// Every byte crosses the open internet through the deployed daemon; nothing 22// loopback, nothing mocked. Requires /tmp/mozilla_certdata.txt staged. 23// license_tier: ORIGINAL 24 25import "nx_syscalls.nx" 26import "nx_gate_emit_lib.nx" 27import "nx_x509_trust_store.nx" 28import "nx_trust_store_load_from_certdata.nx" 29import "nx_tls13_client_validate_certificate.nx" 30import "nx_tls13_client_session_run.nx" 31import "nx_dns_resolve_a_record.nx" 32import "nx_https_url_connect.nx" 33import "nx_websocket_frame.nx" 34import "nx_websocket_client_upgrade.nx" 35 36 37// Slot layout for the per-connection state array `c` (*i64, RG_SLOTS entries, allocated by this 38// file). The whole block was missing -- defined in NO file in the tree -- so nx_parse stopped at the 39// first use (RG_S) and both gates had been unbuildable. These are private indices, so any distinct 40// assignment is correct; RG_SLOTS is the allocation count. 41const RG_FD: i64 = 0 42const RG_S: i64 = 1 43const RG_ACC: i64 = 2 44const RG_ACC_CAP: i64 = 3 45const RG_ACC_LEN: i64 = 4 46const RG_ACC_OFF: i64 = 5 47const RG_SLOTS: i64 = 6 48 49 50func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 51" as *u8); return ok } 52func rg_tls_send(c: *i64, buf: *u8, n: i64) -> i64 { 53 let s: *Tls13ClientSession = c[RG_S] as *Tls13ClientSession 54 let rec: *u8 = sys_mmap(n + 64) 55 let hdr: *u8 = rec 56 let ct: *u8 = rec + NX_TLS13_RECORD_HEADER_LEN 57 let tag: *u8 = rec + NX_TLS13_RECORD_HEADER_LEN + n + 1 58 let v: i64 = nx_tls13_record_encrypt_v2( 59 s.cipher_suite, s.client_app_traffic_key, s.client_app_iv, 60 s.client_app_seq, buf, n, NX_TLS13_CT_APPLICATION_DATA, 0, 61 hdr, ct, tag) 62 s.client_app_seq = s.client_app_seq + 1 63 if v != NX_TLS13_REC_VERDICT_OK { return 0 - 1 } 64 let total: i64 = NX_TLS13_RECORD_HEADER_LEN + n + 1 + NX_TLS13_RECORD_TAG_LEN 65 var off: i64 = 0 66 while off < total { 67 let w: i64 = sys_write(c[RG_FD], (rec as i64 + off) as *u8, total - off) 68 if w <= 0 { return 0 - 1 } 69 off = off + w 70 } 71 return 0 72} 73 74func rg_pump(c: *i64) -> i64 { 75 let s: *Tls13ClientSession = c[RG_S] as *Tls13ClientSession 76 let rec: *u8 = sys_mmap(16700) 77 let total: i64 = nx_tls13_read_record_from_fd(c[RG_FD], rec, 16700) 78 if total < 0 { return 0 - 1 } 79 let ct_len: i64 = total - NX_TLS13_RECORD_HEADER_LEN - NX_TLS13_RECORD_TAG_LEN 80 if ct_len <= 0 { return 0 - 1 } 81 let plain: *u8 = sys_mmap(ct_len + 16) 82 let ctp: *i64 = sys_mmap(16) as *i64 83 let lnp: *i64 = sys_mmap(16) as *i64 84 let v: i64 = nx_tls13_record_decrypt_v2( 85 s.cipher_suite, s.server_app_traffic_key, s.server_app_iv, 86 s.server_app_seq, rec, rec + NX_TLS13_RECORD_HEADER_LEN, ct_len, 87 rec + total - NX_TLS13_RECORD_TAG_LEN, plain, ctp, lnp) 88 s.server_app_seq = s.server_app_seq + 1 89 if v != NX_TLS13_REC_VERDICT_OK { return 0 - 2 } 90 if *ctp == NX_TLS13_CT_ALERT { return 0 - 3 } 91 if *ctp != NX_TLS13_CT_APPLICATION_DATA { return 0 } 92 let acc: *u8 = c[RG_ACC] as *u8 93 var w: i64 = c[RG_ACC_LEN] 94 if w + *lnp > c[RG_ACC_CAP] { return 0 - 4 } 95 var i: i64 = 0 96 while i < *lnp { acc[w + i] = plain[i]; i = i + 1 } 97 c[RG_ACC_LEN] = w + *lnp 98 return *lnp 99} 100 101func rg_next_frame(c: *i64, f: *WsFrame) -> i64 { 102 var tries: i64 = 0 103 while tries < 256 { 104 let acc: *u8 = c[RG_ACC] as *u8 105 let v: i64 = ws_parse_frame(acc, c[RG_ACC_LEN], c[RG_ACC_OFF], f) 106 if v == 0 { 107 c[RG_ACC_OFF] = c[RG_ACC_OFF] + f.frame_len 108 return 0 109 } 110 let p: i64 = rg_pump(c) 111 if p < 0 { return p } 112 tries = tries + 1 113 } 114 return 0 - 9 115} 116 117// reset the accumulator so long phases never overflow the cap 118func rg_reset_acc(c: *i64) -> i64 { 119 let acc: *u8 = c[RG_ACC] as *u8 120 let keep: i64 = c[RG_ACC_LEN] - c[RG_ACC_OFF] 121 var i: i64 = 0 122 while i < keep { acc[i] = acc[c[RG_ACC_OFF] + i]; i = i + 1 } 123 c[RG_ACC_LEN] = keep 124 c[RG_ACC_OFF] = 0 125 return 0 126} 127 128func rg_send_ws(c: *i64, opcode: i64, payload: *u8, n: i64, mask: i64) -> i64 { 129 let buf: *u8 = sys_mmap(n + 32) 130 let hl: i64 = ws_build_header(buf, n + 32, 1, opcode, 1, mask, n) 131 if hl < 0 { return 0 - 1 } 132 var i: i64 = 0 133 while i < n { buf[hl + i] = payload[i]; i = i + 1 } 134 ws_apply_mask(buf, hl, n, mask) 135 return rg_tls_send(c, buf, hl + n) 136} 137 138func rg_join(c: *i64, ipv4: i64, sni: *u8, sni_n: i64, path: *u8, path_n: i64, 139 store: *TrustStore, seed: i64) -> i64 { 140 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 141 if fd < 0 { return 0 - 1 } 142 sys_set_socket_timeout(fd, 15) 143 let sa: *u8 = sys_mmap(16) 144 nx_https_build_sockaddr(sa, ipv4, 443) 145 if nx_connect_bounded(fd, sa, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0 - 2 } 146 let cr: *u8 = sys_mmap(32) 147 let priv: *u8 = sys_mmap(32) 148 var i: i64 = 0 149 while i < 32 { cr[i] = ((seed * 37 + i * 11 + 5) & 0xff) as u8; priv[i] = ((seed * 53 + i * 7 + 9) & 0xff) as u8; i = i + 1 } 150 let vraw: *u8 = sys_mmap(64) 151 let val_ctx: *TlsValidationContext = vraw as *TlsValidationContext 152 val_ctx.store = store 153 val_ctx.sni_host = sni 154 val_ctx.sni_host_len = sni_n 155 val_ctx.now_epoch = sys_now_realtime_sec() 156 let r: i64 = nx_tls13_client_session_run(fd, sni, sni_n, cr, priv, val_ctx) 157 if r < 0 { g_puts(" tls run verdict=" as *u8); g_pn(r); g_puts("\n" as *u8); sys_close(fd); return 0 - 3 } 158 c[RG_FD] = fd 159 c[RG_S] = r 160 c[RG_ACC] = sys_mmap(4194304) as i64 161 c[RG_ACC_LEN] = 0 162 c[RG_ACC_OFF] = 0 163 c[RG_ACC_CAP] = 4194304 164 let req: *u8 = sys_mmap(2048) 165 let key24: *u8 = sys_mmap(32) 166 let rn: i64 = nx_ws_client_build_request(req, 2048, sni, sni_n, path, path_n, 443, 0, key24) 167 if rn <= 0 { return 0 - 4 } 168 if rg_tls_send(c, req, rn) < 0 { return 0 - 5 } 169 var hend: i64 = 0 - 1 170 var tries: i64 = 0 171 while tries < 32 { 172 let acc: *u8 = c[RG_ACC] as *u8 173 var j: i64 = 0 174 while j + 3 < c[RG_ACC_LEN] { 175 var hit: i64 = 1 176 if acc[j] != (13 as u8) { hit = 0 } 177 if acc[j+1] != (10 as u8) { hit = 0 } 178 if acc[j+2] != (13 as u8) { hit = 0 } 179 if acc[j+3] != (10 as u8) { hit = 0 } 180 if hit == 1 { hend = j + 4; j = c[RG_ACC_LEN] } else { j = j + 1 } 181 } 182 if hend > 0 { tries = 32 } else { 183 if rg_pump(c) < 0 { return 0 - 6 } 184 tries = tries + 1 185 } 186 } 187 if hend < 0 { return 0 - 6 } 188 let acc2: *u8 = c[RG_ACC] as *u8 189 let uv: i64 = nx_ws_client_validate_response(acc2, hend, key24) 190 if uv != NX_WSCU_OK { return 0 - 7 } 191 c[RG_ACC_OFF] = hend 192 return 0 193} 194 195// media payload: [kind][8B id][u32 seq LE][u64 sent_us LE][body...] 196func rg_media_ts(out: *u8, kind: i64, id: *u8, seq: i64, body_n: i64) -> i64 { 197 out[0] = kind as u8 198 var i: i64 = 0 199 while i < 8 { out[1 + i] = id[i]; i = i + 1 } 200 out[9] = (seq & 255) as u8 201 out[10] = ((seq / 256) & 255) as u8 202 out[11] = ((seq / 65536) & 255) as u8 203 out[12] = ((seq / 16777216) & 255) as u8 204 var t: i64 = sys_now_us() 205 i = 0 206 while i < 8 { out[13 + i] = (t & 255) as u8; t = t / 256; i = i + 1 } 207 i = 0 208 while i < body_n { out[21 + i] = ((seq * 31 + i * 7 + 3) & 0xff) as u8; i = i + 1 } 209 return 21 + body_n 210} 211 212func rg_read_ts(acc: *u8, off: i64) -> i64 { 213 var t: i64 = 0 214 var i: i64 = 7 215 while i >= 0 { 216 t = t * 256 + (acc[off + 13 + i] & 0xff) 217 i = i - 1 218 } 219 return t 220} 221 222// insertion-sort a small i64 array ascending 223func rg_sort(a: *i64, n: i64) -> i64 { 224 var i: i64 = 1 225 while i < n { 226 let v: i64 = a[i] 227 var j: i64 = i - 1 228 var stop: i64 = 0 229 while stop == 0 { 230 if j < 0 { stop = 1 } 231 if stop == 0 { if a[j] <= v { stop = 1 } } 232 if stop == 0 { a[j + 1] = a[j]; j = j - 1 } 233 } 234 a[j + 1] = v 235 i = i + 1 236 } 237 return 0 238} 239 240// receive ONE binary frame at c; returns latency usec (recv-send) or negative 241func rg_recv_lat(c: *i64, f: *WsFrame) -> i64 { 242 if rg_next_frame(c, f) != 0 { return 0 - 1 } 243 if f.opcode != WS_OP_BINARY { return 0 - 2 } 244 let acc: *u8 = c[RG_ACC] as *u8 245 let sent: i64 = rg_read_ts(acc, f.payload_off) 246 return sys_now_us() - sent 247} 248 249// fork a sender child: streams `count` frames of `body_n` bytes from A 250func rg_fork_sender(ca: *i64, id: *u8, count: i64, body_n: i64) -> i64 { 251 let pid: i64 = sys_fork() 252 if pid != 0 { return pid } 253 let frm: *u8 = sys_mmap(body_n + 64) 254 var s: i64 = 0 255 while s < count { 256 let n: i64 = rg_media_ts(frm, 0x56, id, s, body_n) 257 if rg_send_ws(ca, WS_OP_BINARY, frm, n, 0x5a5a0000 + s) != 0 { sys_exit(2) } 258 s = s + 1 259 } 260 sys_exit(0) 261 return 0 262} 263 264func rg_kill(pid: i64) -> i64 { 265 __syscall(129, pid, 9, 0, 0, 0, 0) // rv64 kill=129. The old comment called raw x86 62 a 'table-gap escape' -- it is not a gap, 62 IS an RV64 KEY and the backend translated it to lseek(8), so the kill never happened (debt idx 2277) 266 let st: *i64 = sys_mmap(16) as *i64 267 sys_wait4(pid, st, 0) 268 return 0 269} 270 271func main() -> i64 { 272 g_puts("nx_room_perf gate (MEASURED live room performance)\n" as *u8) 273 var pass: i64 = 0 274 var total: i64 = 0 275 276 let cpath: *u8 = "/tmp/mozilla_certdata.txt" as *u8 277 let lr: i64 = nx_trust_store_load_from_certdata(cpath, 300, 4194304) 278 if lr <= 0 { g_puts("FAIL trust store load\n" as *u8); return 2 } 279 let store: *TrustStore = lr as *TrustStore 280 let host: *u8 = "nishifamily.com" as *u8 281 let hn: i64 = 15 282 let dr: *DnsResolveResult = nx_dns_resolve_default(host, hn, sys_now_realtime_sec()) 283 if dr.verdict != NX_DNS_R_OK { g_puts("FAIL dns\n" as *u8); return 2 } 284 let path: *u8 = "/signal/perfroomgate" as *u8 285 let pn: i64 = g_slen(path) 286 287 let ca: *i64 = sys_mmap(RG_SLOTS * 8) as *i64 288 let cb: *i64 = sys_mmap(RG_SLOTS * 8) as *i64 289 let cc: *i64 = sys_mmap(RG_SLOTS * 8) as *i64 290 let ja: i64 = rg_join(ca, dr.ipv4_packed, host, hn, path, pn, store, 11) 291 let jb: i64 = rg_join(cb, dr.ipv4_packed, host, hn, path, pn, store, 12) 292 let jc: i64 = rg_join(cc, dr.ipv4_packed, host, hn, path, pn, store, 13) 293 pass = pass + g_check("3 users joined (TLS1.3 real-CA + wss 101, public)" as *u8, 294 (ja == 0) + (jb == 0) + (jc == 0) == 3); total = total + 1 295 if ja != 0 { return 1 } 296 if jb != 0 { return 1 } 297 if jc != 0 { return 1 } 298 299 let fraw: *u8 = sys_mmap(128) 300 let f: *WsFrame = fraw as *WsFrame 301 let lats: *i64 = sys_mmap(2048) as *i64 302 303 // ---- P1: unloaded latency, 20 paced 64B frames A -> B (C reads too) ---- 304 let frm: *u8 = sys_mmap(512) 305 var got1: i64 = 0 306 var s: i64 = 0 307 while s < 20 { 308 let n: i64 = rg_media_ts(frm, 0x56, "useraaaa" as *u8, s, 64) 309 rg_send_ws(ca, WS_OP_BINARY, frm, n, 0x11110000 + s) 310 let lb: i64 = rg_recv_lat(cb, f) 311 if lb >= 0 { lats[got1] = lb; got1 = got1 + 1 } 312 rg_next_frame(cc, f) 313 sys_sleep_ms(30) 314 s = s + 1 315 } 316 rg_sort(lats, got1) 317 g_puts("PERF P1 unloaded: delivered=" as *u8); g_pn(got1) 318 g_puts("/20 p50_us=" as *u8); g_pn(lats[got1 / 2]) 319 g_puts(" max_us=" as *u8); g_pn(lats[got1 - 1]); g_puts("\n" as *u8) 320 pass = pass + g_check("P1: 20/20 paced frames delivered to B" as *u8, got1 == 20); total = total + 1 321 322 // ---- P2: loaded throughput, forked sender streams 120 x 8KB ---- 323 rg_reset_acc(cb); rg_reset_acc(cc) 324 let t0: i64 = sys_now_us() 325 let pid2: i64 = rg_fork_sender(ca, "useraaaa" as *u8, 120, 8000) 326 var gb: i64 = 0 327 var gc: i64 = 0 328 var lat_n: i64 = 0 329 var k: i64 = 0 330 var alive: i64 = 1 331 while k < 120 { 332 if alive == 1 { 333 let lb: i64 = rg_recv_lat(cb, f) 334 if lb >= 0 { gb = gb + 1; lats[lat_n] = lb; lat_n = lat_n + 1 } else { alive = 0 } 335 if rg_next_frame(cc, f) == 0 { gc = gc + 1 } else { alive = 0 } 336 if (k & 15) == 15 { rg_reset_acc(cb); rg_reset_acc(cc) } 337 } 338 k = k + 1 339 } 340 let t1: i64 = sys_now_us() 341 rg_kill(pid2) 342 rg_sort(lats, lat_n) 343 let wall_ms: i64 = (t1 - t0) / 1000 344 var kbps: i64 = 0 345 if wall_ms > 0 { kbps = (gb * 8021) / wall_ms } 346 g_puts("PERF P2 loaded: B=" as *u8); g_pn(gb) 347 g_puts("/120 C=" as *u8); g_pn(gc) 348 g_puts("/120 wall_ms=" as *u8); g_pn(wall_ms) 349 g_puts(" delivered_KBps=" as *u8); g_pn(kbps) 350 g_puts(" loaded_p50_us=" as *u8); g_pn(lats[lat_n / 2]) 351 g_puts(" loaded_max_us=" as *u8); g_pn(lats[lat_n - 1]); g_puts("\n" as *u8) 352 pass = pass + g_check("P2: all 120 x 8KB delivered to BOTH B and C under load" as *u8, 353 (gb == 120) + (gc == 120) == 2); total = total + 1 354 355 // ---- P4: slow reader -- C stops reading; B must still get all 96 ---- 356 // A's parent-side TLS seq is STALE after P2's forked sender advanced it 357 // in the child, so A is RETIRED (closed) and a fresh client D joins as 358 // the firehose: room = B (reading), C (asleep), D (forked sender). 359 sys_close(ca[RG_FD]) 360 let cd: *i64 = sys_mmap(RG_SLOTS * 8) as *i64 361 let jd: i64 = rg_join(cd, dr.ipv4_packed, host, hn, path, pn, store, 14) 362 pass = pass + g_check("P4 setup: fresh user D joined as firehose" as *u8, jd == 0); total = total + 1 363 rg_reset_acc(cb); rg_reset_acc(cc) 364 sys_set_socket_timeout(cb[RG_FD], 8) 365 let pid4: i64 = rg_fork_sender(cd, "userdddd" as *u8, 400, 8000) 366 var gb4: i64 = 0 367 var k4: i64 = 0 368 var alive4: i64 = 1 369 while k4 < 400 { 370 if alive4 == 1 { 371 if rg_recv_lat(cb, f) >= 0 { gb4 = gb4 + 1 } else { alive4 = 0 } 372 if (k4 & 15) == 15 { rg_reset_acc(cb) } 373 } 374 k4 = k4 + 1 375 } 376 rg_kill(pid4) 377 g_puts("PERF P4 slow-reader: B_delivered=" as *u8); g_pn(gb4) 378 g_puts("/400 = 3.2MB past a dead peer (v2 relay wedges when C's chain buffers fill)\n" as *u8) 379 pass = pass + g_check("P4: slow peer C does NOT stall delivery to B (400/400)" as *u8, gb4 == 400); total = total + 1 380 381 sys_close(cb[RG_FD]); sys_close(cc[RG_FD]); sys_close(cd[RG_FD]) 382 g_puts("---- room_perf gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 383 if pass == total { return 0 } 384 return 1 385}