code wiki / _hdl_build / nx_hget_leak_probe.nx

nx_hget_leak_probe.nx

buildroot/runtime/_hdl_build/nx_hget_leak_probe.nx

5185 B110 linesdepth 3pulls 4 transitivereach 0 importersview sourcekind probe
docsdependenciesstructsconstsfunctions

about

nx_hget_leak_probe.nx -- MEASURES the per-call allocation leak in ss_hget (2026-07-30). WHAT IT PROVES: ss_hget used to sys_mmap TWO scratch buffers PER INVOCATION and never free them. sys_mmap is a real mmap syscall (nx_syscalls.nx:167), not a bump allocator, so the kernel rounds each to a full page => ~8 KB leaked PER CALL. ss_hget is the hottest read primitive in the tree (205 call sites; the loaders call it ONCE PER ROW), so the leak scales with ROWS SCANNED, not with stores opened -- which is why it hid behind the per-open leak everyone was looking at. THE MEASUREMENT IS THE POINT: run N hgets and read our OWN VSZ before and after. A fixed ss_hget must show delta_kb == 0 (scratch allocated once, on first call). The pre-fix code would show roughly N * 8 KB. Reuses nx_leak_check_lib (lc_vsz) rather than re-deriving /proc parsing -- rule 15. NON-VACUITY: the loop must do REAL work, so the probe seeds a store, reads a key back, and asserts the VALUE is correct. A probe that measured memory while looking up a missing key would pass while exercising almost nothing (ss_hget returns early on ns==0, before the allocations).

dependencies 3 imports · 0 importers

nx_syscalls.nx nx_seg_store.nx nx_vsz_watchdog_core.nx nx_hget_leak_probe.nx

imports: nx_syscalls.nxnx_seg_store.nxnx_vsz_watchdog_core.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main ss_begin ss_begin_cap sys_mmap ss_add ss_add2 ss_w32 ss_len ss_commit ss_segid_ok sys_mmap ↻ ss_cat ss_catn sys_mmap ↻ sys_write ss_write_seg ss_segid_ok ↻ sys_mmap ↻ ss_cat ↻ ss_catn ↻ sys_write ↻ ss_segname ss_cat ↻ ss_catn ↻ ss_writefile sys_openat_wr sys_write ↻ sys_close sys_fsync sys_renameat ss_build_keys sys_mmap ↻ ss_r32 ss_kcmp ss_w32 ↻ ss_build_terms sys_mmap ↻ ss_tok_table ss_r32 ↻ ss_tok_next2

structs

none

consts

19const HL_MAGIC_1024: i64 = 1024
21const HL_ITERS: i64 = 4000 // enough that a 8KB/call leak is unmissable (~32 MB)
22const HL_TOLERANCE_KB: i64 = 64 // page-granular slack; a real leak here is orders of magnitude bigger

functions

24func hl_puts(s: *u8) -> i64
called by 2: hl_putnmain calls 1: sys_write
30func hl_putn(v: i64) -> i64
called by 1: main calls 3: sys_mmaphl_putssys_write
44func main() -> i64