code wiki / (root) / nx_bench_dist_persist_test.nx

nx_bench_dist_persist_test.nx source

↩ module page · 197 lines · 7931 B

1// nx_bench_dist_persist_test.nx -- run distribution + persist to disk. 2// 3// Composes the distribution measurement primitive with the disk-write 4// persistence primitive. Produces a REAL TSV file at 5// /tmp/nx_bench_dist.tsv 6// containing one header + N data rows + summary stats. 7// 8// This is the substrate-honest end-to-end workflow the s-class 9// comparison campaign needs: measurement happens, bytes hit disk, 10// external tools (sort / awk / future llama.cpp comparison rigs) read 11// the file and diff against their own. 12// 13// After the smoke runs, the operator can: 14// cat /tmp/nx_bench_dist.tsv 15// sort -k7n /tmp/nx_bench_dist.tsv 16// awk -F'\t' '{print $1, $8}' /tmp/nx_bench_dist.tsv 17// 18// And see real persisted substrate measurements. 19 20import "nx_syscalls.nx" 21import "nx_tier.nx" 22import "nx_clock.nx" 23import "nx_actor.nx" 24import "nx_message.nx" 25import "nx_session.nx" 26import "nx_bench_companion.nx" 27import "nx_bench_companion_timed.nx" 28import "nx_bench_companion_tsv.nx" 29import "nx_bench_stats.nx" 30import "nx_bench_tsv_persist.nx" 31import "nx_gguf_fixture_tiny.nx" 32import "nx_actor_role_llm_v2.nx" 33 34// ===== Emit a decimal i64 into a byte buffer; return new offset ===== 35 36func _emit_dec_to_buf(buf: *u8, off: nx_int, cap: nx_int, n: i64) -> nx_int { 37 if off >= cap { return 0 - 1 } 38 if n == 0 { buf[off] = 0x30 as u8; return off + 1 } 39 var v: i64 = n 40 var neg: nx_int = 0 41 if v < 0 { neg = 1; v = 0 - v } 42 let scratch: *u8 = sys_mmap(32) 43 var k: nx_int = 0 44 while v > 0 { 45 scratch[k] = (0x30 + (v - (v / 10) * 10)) as u8 46 v = v / 10 47 k = k + 1 48 } 49 var out: nx_int = off 50 if neg == 1 { 51 if out >= cap { return 0 - 1 } 52 buf[out] = 0x2D as u8 53 out = out + 1 54 } 55 while k > 0 { 56 k = k - 1 57 if out >= cap { return 0 - 1 } 58 buf[out] = scratch[k] 59 out = out + 1 60 } 61 return out 62} 63 64// ===== One scenario run = one wall-clock sample ================= 65 66func _drive_one_run(seed: i64, n_iters: nx_int, now: nx_size) -> i64 { 67 let fix: *NxGgufFixtureBundle = nx_gft_build_tiny_llama(seed) 68 if nx_gft_is_built(fix) != 1 { return 0 - 1 } 69 let s: *NxSession = nx_session_new_default(now) 70 if nx_session_is_ready(s) != 1 { return 0 - 1 } 71 let LLM: nx_int = 7001 72 nx_session_spawn_actor(s, LLM, 1, 80, 0, now) 73 let prompt: *u8 = sys_mmap(1); prompt[0] = 0x61 74 let ctx: *NxLlmV2ActorCtx = nx_lv_actor_new( 75 fix.spec, fix.gguf_buf, fix.hdr, fix.bpe, prompt, 1, 76 1024, 4, fix.prng_state, 10000, 724) 77 if (ctx as i64) == 0 { return 0 - 1 } 78 let start: i64 = nx_clock_monotonic_ns() 79 var iter: nx_int = 0 80 var tick: nx_size = now + 100 81 while iter < n_iters { 82 nx_lv_actor_step(ctx, s.scheduler, s.bus, LLM, tick); tick = tick + 50 83 nx_lv_actor_step(ctx, s.scheduler, s.bus, LLM, tick); tick = tick + 50 84 if ctx.runner_result < 0 { return 0 - 1 } 85 nx_lv_actor_step(ctx, s.scheduler, s.bus, LLM, tick); tick = tick + 50 86 if iter < (n_iters - 1) { 87 prompt[0] = nx_gft_vocab_byte(fix, ctx.runner_result) as u8 88 nx_lv_actor_reset_for_next_token(ctx, s.scheduler, LLM, prompt, 1) 89 } 90 iter = iter + 1 91 } 92 let end: i64 = nx_clock_monotonic_ns() 93 return (end - start) / 1000 94} 95 96func main() -> i64 { 97 let now: nx_size = 1000000 98 let N_RUNS: nx_int = 10 99 let N_ITERS: nx_int = 10 100 101 // ===== Path /tmp/nx_bench_dist.tsv (22 bytes) ===== 102 let path: *u8 = sys_mmap(32) 103 path[0]=0x2F as u8; path[1]=0x74 as u8; path[2]=0x6D as u8; path[3]=0x70 as u8 104 path[4]=0x2F as u8; path[5]=0x6E as u8; path[6]=0x78 as u8; path[7]=0x5F as u8 105 path[8]=0x62 as u8; path[9]=0x65 as u8; path[10]=0x6E as u8; path[11]=0x63 as u8 106 path[12]=0x68 as u8; path[13]=0x5F as u8; path[14]=0x64 as u8; path[15]=0x69 as u8 107 path[16]=0x73 as u8; path[17]=0x74 as u8; path[18]=0x2E as u8; path[19]=0x74 as u8 108 path[20]=0x73 as u8; path[21]=0x76 as u8 109 let path_len: nx_int = 22 110 111 // ===== Truncate file via O_TRUNC opener ===== 112 let pz: *u8 = sys_mmap(path_len + 1) 113 var pi: nx_int = 0 114 while pi < path_len { pz[pi] = path[pi]; pi = pi + 1 } 115 pz[path_len] = 0 as u8 116 let fd_trunc: i64 = sys_openat_wr(pz, 420) 117 if fd_trunc < 0 { return 1 } 118 sys_close(fd_trunc) 119 120 // ===== Write header row: "label\tsample_us\n" ===== 121 let hdr: *u8 = sys_mmap(16) 122 hdr[0]=0x6C as u8; hdr[1]=0x61 as u8; hdr[2]=0x62 as u8; hdr[3]=0x65 as u8 123 hdr[4]=0x6C as u8; hdr[5]=0x09 as u8; hdr[6]=0x73 as u8; hdr[7]=0x61 as u8 124 hdr[8]=0x6D as u8; hdr[9]=0x70 as u8; hdr[10]=0x6C as u8; hdr[11]=0x65 as u8 125 hdr[12]=0x5F as u8; hdr[13]=0x75 as u8; hdr[14]=0x73 as u8; hdr[15]=0x0A as u8 126 if nx_bc_persist_row(path, path_len, hdr, 16) != 16 { return 2 } 127 128 // ===== Collect + persist per-run samples ===== 129 let samples_buf: *u8 = sys_mmap(N_RUNS * 8) 130 let samples: *i64 = samples_buf as *i64 131 132 // Per-row buffer: "v2_dist_<i>\t<elapsed_us>\n" 133 let row_buf: *u8 = sys_mmap(64) 134 135 var r: nx_int = 0 136 while r < N_RUNS { 137 let elapsed: i64 = _drive_one_run(0xD000 + (r as i64), N_ITERS, now) 138 if elapsed < 0 { return 10 + r } 139 samples[r] = elapsed 140 141 // Build row: "v2_dist_" (8) + digit + "\t" + elapsed_us + "\n" 142 row_buf[0]=0x76 as u8; row_buf[1]=0x32 as u8; row_buf[2]=0x5F as u8 143 row_buf[3]=0x64 as u8; row_buf[4]=0x69 as u8; row_buf[5]=0x73 as u8 144 row_buf[6]=0x74 as u8; row_buf[7]=0x5F as u8 145 var off: nx_int = _emit_dec_to_buf(row_buf, 8, 64, r as i64) 146 if off < 0 { return 100 + r } 147 row_buf[off] = 0x09 as u8 148 off = off + 1 149 off = _emit_dec_to_buf(row_buf, off, 64, elapsed) 150 if off < 0 { return 200 + r } 151 row_buf[off] = 0x0A as u8 152 off = off + 1 153 if nx_bc_persist_row(path, path_len, row_buf, off) != (off as i64) { return 300 + r } 154 r = r + 1 155 } 156 157 // ===== Compute stats + persist summary row ===== 158 let stats: *NxBenchStats = nx_bst_new() 159 nx_bench_stats_compute(samples, N_RUNS, stats) 160 161 // Summary row: "STATS\t<n>\t<min>\t<max>\t<mean>\t<p50>\t<p95>\t<stddev>\n" 162 let sbuf: *u8 = sys_mmap(128) 163 sbuf[0]=0x53 as u8; sbuf[1]=0x54 as u8; sbuf[2]=0x41 as u8 164 sbuf[3]=0x54 as u8; sbuf[4]=0x53 as u8; sbuf[5]=0x09 as u8 165 var soff: nx_int = 6 166 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_n(stats) as i64); sbuf[soff] = 0x09 as u8; soff = soff + 1 167 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_min(stats)); sbuf[soff] = 0x09 as u8; soff = soff + 1 168 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_max(stats)); sbuf[soff] = 0x09 as u8; soff = soff + 1 169 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_mean(stats)); sbuf[soff] = 0x09 as u8; soff = soff + 1 170 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_p50(stats)); sbuf[soff] = 0x09 as u8; soff = soff + 1 171 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_p95(stats)); sbuf[soff] = 0x09 as u8; soff = soff + 1 172 soff = _emit_dec_to_buf(sbuf, soff, 128, nx_bst_stddev(stats)) 173 sbuf[soff] = 0x0A as u8; soff = soff + 1 174 175 if nx_bc_persist_row(path, path_len, sbuf, soff) != (soff as i64) { return 400 } 176 177 // ===== Read back + verify file is non-empty + ends with \n ===== 178 let fd_r: i64 = sys_openat_rd(pz) 179 if fd_r < 0 { return 500 } 180 let rb: *u8 = sys_mmap(1024) 181 let n_read: i64 = sys_read(fd_r, rb, 1024) 182 sys_close(fd_r) 183 if n_read <= 0 { return 501 } 184 if rb[n_read - 1] != (0x0A as u8) { return 502 } 185 186 // First 5 bytes must be "label" (header start) 187 if rb[0] != (0x6C as u8) { return 503 } 188 if rb[1] != (0x61 as u8) { return 504 } 189 if rb[2] != (0x62 as u8) { return 505 } 190 191 // Substrate invariants 192 if nx_bst_n(stats) != N_RUNS { return 600 } 193 if nx_bst_p50(stats) <= 0 { return 601 } 194 if nx_bst_p95(stats) < nx_bst_p50(stats) { return 602 } 195 196 return 0 197}