FABRIC-2.md Section Q: heartbeat-tick ACL-TTL remeasurement finds the
instrument blind to the effect, not a corrected number Per Captain Bob's correction (heartbeat tick counter is the sole canonical clock, not wall-clock), added HEARTBEAT-TICKS@ and re-ran the ACL-TTL overhead measurement using tick deltas. Diagnostics confirmed the counter is a FORTH-level colon-word-dispatch counter (frozen at idle, jumps with real work) -- not a wall-clock proxy. A pilot pair (amd64, seed 12345, 30 reps, ACL disabled vs enabled) produced byte-identical deltas (261064 ticks both runs): acl_recheck() runs at the C dispatch level and doesn't change which/how many colon words execute, so it's invisible to a counter gated on colon-word-entry count. Root-caused, not proceeding to the full 18-cell campaign -- every cell would read +0.00% by construction. Section P's wall-clock numbers stand as the best estimate on record pending a instrument that can see per-dispatch cost rather than control-flow shape. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
a7a837e136
commit
3998ce6aaf
+80
@@ -2187,3 +2187,83 @@ effect size. A tighter measurement would need either (a) many more replications
|
||||
shrink the standard error, or (b) reading a VM-internal tick/cycle counter directly (matching
|
||||
the original campaign's own method) rather than host-side wall-clock bracketing. Neither
|
||||
attempted here; scoped as a natural next step, not undertaken in this pass.
|
||||
|
||||
---
|
||||
|
||||
## Q. ACL-TTL overhead via heartbeat ticks — instrument found blind to the effect, 2026-08-20/21
|
||||
|
||||
Section P's wall-clock methodology was flagged by Captain Bob as a direct violation of
|
||||
established project law: **the adaptive heartbeat tick counter is the one and only clock**,
|
||||
not host wall-clock. Correcting for this required a new read-only accessor and a re-run —
|
||||
the re-run surfaced a real, substantive negative result rather than a corrected number.
|
||||
|
||||
**`HEARTBEAT-TICKS@` ( -- n ).** Added to `src/word_source/starforth_words.c`, pushes
|
||||
`vm->heartbeat.tick_count`. Read-only by design — no corresponding store word. Three-arch
|
||||
QEMU acceptance (amd64/aarch64/riscv64): POST 1012/0/0 on each, word live-tested returning a
|
||||
real, non-zero count on all three. Committed `0b11f92` (word) + `a7a837e` (acceptance logs).
|
||||
|
||||
**Diagnostic checks, before trusting the instrument for a campaign** (amd64 only, per
|
||||
advisor guidance — cheaper than discovering the same problem 18 cells in):
|
||||
|
||||
1. **Idle behavior.** Read at `ok>`, wait 30s of real wall-clock time doing nothing, read
|
||||
again: **frozen** (`77` both times). Traced to `sk_repl_idle()` in
|
||||
`src/starkernel/repl.c` — a documented placeholder no-op. The idle poll loop services a
|
||||
*separate* low-level ISR tick counter (`heartbeat_ticks()`/`heartbeat_service()`) but never
|
||||
calls `vm_tick()` on the Hera VM itself, so `vm->heartbeat.tick_count` does not advance
|
||||
from real time passing while idle.
|
||||
2. **Work sensitivity.** Loaded `doe.4th`, ran a trivial 2-rep `EXEC-DOE`: ticks jumped
|
||||
`77 → 17600`. Confirmed the counter *does* respond to VM activity — just not to elapsed
|
||||
time.
|
||||
3. **Mechanism.** `src/starkernel/vm/vm_core.c:813-818`: inside `execute_colon_word` (the
|
||||
inner FORTH interpreter loop), `vm->heartbeat.check_counter` increments once per colon-word
|
||||
entered; every `HEARTBEAT_CHECK_FREQUENCY` such entries, `vm_heartbeat_run_cycle()` fires
|
||||
and increments `tick_count`. **This is a FORTH-level colon-word-dispatch counter, gated at
|
||||
a fixed cadence — not a wall-clock proxy, and not sensitive to per-dispatch CPU cost.**
|
||||
Reconciled against the boot-time `Heartbeat: 3007 ticks` line: that's a *different* counter
|
||||
(`fleet_heartbeat_tick_count` in `capsule_vm_physics.c`, incremented once per live VM's own
|
||||
`vm_tick()` — advances faster in wall-clock terms with more live VMs, not the same
|
||||
quantity). `HEARTBEAT-TICKS@` correctly reads Hera's own counter, the right target for
|
||||
measuring Hera's own `EXEC-DOE` work.
|
||||
4. **HB-OFF/HB-ON interaction.** Confirmed `HB-OFF` only gates `g_doe_log_enabled` (CSV row
|
||||
emission, `src/starkernel/doe_log.c`) — it does not touch `heartbeat_enabled` or `vm_tick()`
|
||||
at `vm_runtime.c:501`. Safe to bracket `EXEC-DOE` with `HB-OFF`/`HB-ON` as before.
|
||||
|
||||
**Pilot pair (not a full campaign): amd64, seed 12345, 30 reps (480/480 rows, 0 errors),
|
||||
ACL disabled vs. enabled**, `EXEC-DOE` bracketed by `HEARTBEAT-TICKS@` reads:
|
||||
|
||||
| ACL state | before | after | delta |
|
||||
|-----------|--------|-------|-------|
|
||||
| disabled | 17600 | 278664 | **261064** |
|
||||
| enabled | 79 | 261143 | **261064** |
|
||||
|
||||
**The deltas are identical to the tick, both runs.** ACL-enabled cell independently confirmed
|
||||
live (`' EXEC ACL-MODE@ .` → `1`, STRICT) before the run, so this isn't a case of ACL silently
|
||||
not being active — enforcement was genuinely on, and it left no trace in this counter.
|
||||
|
||||
**Root cause, not just an observation.** `acl_recheck()` executes inside the C-level word
|
||||
lookup/dispatch machinery per word execution — it does not add, remove, or otherwise change
|
||||
which or how many *colon words* get entered at the FORTH level. `check_counter` only counts
|
||||
colon-word entries (item 3 above). Since `EXEC-DOE`'s control flow is deterministic and
|
||||
identical regardless of ACL state, the exact same number of colon-word-entry events occurs,
|
||||
so the exact same number of `vm_heartbeat_run_cycle()` firings occurs, so `tick_count` advances
|
||||
by the exact same amount — independent of how much *extra C-level work* each dispatch actually
|
||||
cost. This is consistent with, and likely a direct consequence of, this project's deliberate
|
||||
determinism goal (0.000% CV across runs, `.claude/CLAUDE.md`): the heartbeat tick counter is
|
||||
*designed* to be a function of program control flow, immune to real execution-time noise. That
|
||||
is exactly why it is unsuitable for measuring a cost — like ACL's per-dispatch recheck — that
|
||||
changes execution time without changing control flow.
|
||||
|
||||
**Conclusion: the heartbeat tick counter, though correctly identified as this project's one
|
||||
canonical clock, is the wrong instrument for this specific measurement.** It is real, it is
|
||||
read correctly, it responds to VM work — but it is blind by construction to any overhead that
|
||||
doesn't alter which FORTH words get dispatched. ACL-TTL overhead is exactly that kind of cost.
|
||||
**Not proceeding to an 18-cell campaign** — every cell would read +0.00% by construction,
|
||||
which would look like a clean result and would not be one. `HEARTBEAT-TICKS@` remains
|
||||
committed as a real, useful accessor for future work that *does* want a control-flow-invariant
|
||||
clock; it is simply not the right tool for ACL overhead specifically. Section P's wall-clock
|
||||
numbers stand as the best empirical estimate on record (methodologically noisy, not
|
||||
methodologically blind) unless a cycle-accurate or dispatch-level-cost instrument is added.
|
||||
Candidates for a follow-up, not undertaken here: (a) a separate counter incremented inside
|
||||
`acl_recheck()` itself (would directly count ACL work, trivially showing 0 when disabled), or
|
||||
(b) instrumenting at the CPU-cycle level (`rdtsc`/equivalent) around the word-dispatch
|
||||
primitive rather than at the colon-word-entry granularity.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-21T03:09:23Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-21T03:22:02Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user