FABRIC-3.10.8 K-8: free the vocabulary indexes and inference outputs at vm_cleanup
The ~3.4 KB/VM heap residual left after K-4 was each dead VM's CONTEXT and FORTH first-character bucket arrays (84 blocks, 3,400 bytes per worker), plus last_inference_outputs. New vocabulary_free_indexes(); both vm_cleanup()s call it and free the outputs. Per-VM residual is now 232 bytes: the registry node (kept by design) and the vm_physics node (open finding). 3-ISA acceptance clean, hash 0x99b01134c3d3049c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
acea36ea55
commit
f29658a65d
@@ -673,3 +673,34 @@ riscv64's slowest completion halved (15.1 → 7.7 ms), consistent with requests
|
||||
| riscv64 | `logs/20260926-082042` | same; **0 `timed out` lines in the log** |
|
||||
|
||||
**K-6 closes §8 defect 3.**
|
||||
|
||||
### 4.8 K-8 — the ~3.4 KB/VM residual: found and freed (2026-09-26)
|
||||
|
||||
**Investigation** (temporary probe: a kmalloc heap walk and two Mama words, `K8-SNAP` (record every used block) and `K8-DIFF` (list the used blocks that are new since the snapshot, with their first 32 bytes)). amd64. Each run did two warm-up worker cycles (WORKER-BIRTH, SEND, KILL), then snapshot, one cycle, diff, twice.
|
||||
- **Before the fix** (`logs/20260926-083533`): each cycle left **84 new blocks, 3,400 bytes**, identical in both cycles. That is exactly K-4's 95,200 bytes per 28-VM round.
|
||||
- **What they were:** the dead VM's vocabulary search indexes. These are the first-character bucket arrays for CONTEXT and FORTH (`vm->vocab.ctx_fc` / `forth_fc`), built lazily by `fc_rebuild()` and never freed by `vm_cleanup()`.
|
||||
- Reading `vm_cleanup()` turned up one more: `vm->last_inference_outputs` was never freed either.
|
||||
|
||||
**Change.**
|
||||
- New `vocabulary_free_indexes(vm)` (`vocabulary_words.c`) frees both indexes' buckets and clears the cached heads.
|
||||
- Both `vm_cleanup()`s (kernel `vm_core.c`, hosted `vm_bootstrap.c`) call it after the dictionary index, then free `last_inference_outputs`.
|
||||
|
||||
**Evidence, after the fix** (same probe, `logs/20260926-084642`): each cycle leaves **2 blocks, 232 bytes**, identical in both cycles. Both are keyed by the dead VM's id:
|
||||
|
||||
| Block | Size | What | Status |
|
||||
|---|---|---|---|
|
||||
| registry node (`vm_node_t`), state DEAD | 168 B | the VM's registry entry | kept by design: nodes are never freed after boot, so entry pointers stay valid |
|
||||
| `vm_physics_node_t` | 64 B | the VM's fleet-physics node | the MC-0 finding "`vm_physics` nodes are never removed"; **open, awaiting a ruling** |
|
||||
|
||||
- The unexplained residual is gone: 3,400 → 232 bytes per VM, all of it identified.
|
||||
- K-1's "within one allocation" criterion, as written, cannot be met while those two nodes stay after death. The registry node is a design decision; the physics node depends on the ruling above.
|
||||
|
||||
**Standard sequence** (clean build, with the probe reverted; only the four fix files differ from K-6).
|
||||
|
||||
| ISA | log | result |
|
||||
|---|---|---|
|
||||
| amd64 | `logs/20260926-085034` | hash `0x99b01134c3d3049c`, G A=40 B=40, HHH, all ok `3`, ledger unchanged, 0 B idle, 0 / 0 |
|
||||
| aarch64 | `logs/20260926-090043` | same |
|
||||
| riscv64 | `logs/20260926-091122` | same; 0 `timed out` lines |
|
||||
|
||||
**K-8 closes the unexplained part of K-1's heap criterion.**
|
||||
|
||||
Reference in New Issue
Block a user