nx_bench_tsv_persist.nx source
↩ module page · 108 lines · 3827 B
1// nx_bench_tsv_persist.nx -- write bench TSV rows to a real file on disk.
2//
3// Sibling to the emit + parse primitives. Closes the final loop:
4// measurement bytes now persist beyond process exit so cross-runner
5// comparison (Nishi.tsv vs llama_cpp.tsv vs vllm.tsv) reads
6// canonical-format rows from disk.
7//
8// V1 ships:
9// nx_bc_persist_open_append(path, path_len) -> fd or NEGATIVE
10// nx_bc_persist_write(fd, buf, n_bytes) -> bytes_written or NEGATIVE
11// nx_bc_persist_close(fd) -> 0 or NEGATIVE
12// nx_bc_persist_row(path, path_len, buf, n) -> bytes_written or NEGATIVE
13// (one-call wrapper: open-append + write + close)
14//
15// Sealed verdict so callers handle disk failures (ENOENT, EPERM, etc.)
16// as structured negative returns instead of as silent zero-byte writes.
17
18import "nx_syscalls.nx"
19import "nx_tier.nx"
20
21// ===== Sealed verdict ===========================================
22
23const NX_BCPS_OK: nx_int = 0
24const NX_BCPS_OPEN_FAIL: nx_int = 1
25const NX_BCPS_WRITE_FAIL: nx_int = 2
26const NX_BCPS_CLOSE_FAIL: nx_int = 3
27const NX_BCPS_NULL_PATH: nx_int = 4
28const NX_BCPS_NULL_BUF: nx_int = 5
29const NX_BCPS_INVALID: nx_int = 6
30const NX_BCPS_N: nx_int = 7
31
32func nx_bcps_v_is_valid(v: nx_int) -> nx_int {
33 if v < 0 { return 0 }
34 if v >= NX_BCPS_N { return 0 }
35 return 1
36}
37
38// ===== Null-terminate a path buffer ============================
39//
40// sys_openat requires a NUL-terminated path. NishiLang strings are
41// (ptr, len) pairs without trailing NUL. Copy + append.
42
43func _bcps_null_terminate(path: *u8, path_len: nx_int) -> *u8 {
44 let copy: *u8 = sys_mmap(path_len + 1)
45 var i: nx_int = 0
46 while i < path_len {
47 copy[i] = path[i]
48 i = i + 1
49 }
50 copy[path_len] = 0 as u8
51 return copy
52}
53
54// ===== Public: low-level ========================================
55
56func nx_bc_persist_open_append(path: *u8, path_len: nx_int) -> i64 {
57 if (path as i64) == 0 { return 0 - NX_BCPS_NULL_PATH }
58 if path_len <= 0 { return 0 - NX_BCPS_INVALID }
59 let pz: *u8 = _bcps_null_terminate(path, path_len)
60 // Mode 0644 (= 0o644 = 420 decimal) -- read/write owner, read others
61 let fd: i64 = sys_openat_append(pz, 420)
62 if fd < 0 { return 0 - NX_BCPS_OPEN_FAIL }
63 return fd
64}
65
66func nx_bc_persist_write(fd: i64, buf: *u8, n_bytes: nx_int) -> i64 {
67 if fd < 0 { return 0 - NX_BCPS_INVALID }
68 if (buf as i64) == 0 { return 0 - NX_BCPS_NULL_BUF }
69 if n_bytes <= 0 { return 0 - NX_BCPS_INVALID }
70 let written: i64 = sys_write(fd, buf, n_bytes as i64)
71 if written < 0 { return 0 - NX_BCPS_WRITE_FAIL }
72 return written
73}
74
75func nx_bc_persist_close(fd: i64) -> nx_int {
76 if fd < 0 { return NX_BCPS_INVALID }
77 let v: i64 = sys_close(fd)
78 if v < 0 { return NX_BCPS_CLOSE_FAIL }
79 return NX_BCPS_OK
80}
81
82// ===== Public: one-shot wrapper =================================
83//
84// Opens path in append mode, writes one buffer, closes. Idempotent +
85// safe for repeated calls (each call appends; file persists across
86// process exits).
87
88func nx_bc_persist_row(path: *u8, path_len: nx_int,
89 buf: *u8, n_bytes: nx_int) -> i64 {
90 if (path as i64) == 0 { return 0 - NX_BCPS_NULL_PATH }
91 if (buf as i64) == 0 { return 0 - NX_BCPS_NULL_BUF }
92 if path_len <= 0 { return 0 - NX_BCPS_INVALID }
93 if n_bytes <= 0 { return 0 - NX_BCPS_INVALID }
94
95 let fd: i64 = nx_bc_persist_open_append(path, path_len)
96 if fd < 0 { return fd }
97
98 let written: i64 = nx_bc_persist_write(fd, buf, n_bytes)
99 if written < 0 {
100 sys_close(fd)
101 return written
102 }
103
104 let v_close: nx_int = nx_bc_persist_close(fd)
105 if v_close != NX_BCPS_OK { return 0 - (v_close as i64) }
106
107 return written
108}