From c0bbff21c921782a6a8ee8223b6c726ea9052ba3 Mon Sep 17 00:00:00 2001 From: Robert Allan James Date: Wed, 5 Aug 2026 11:18:22 -0400 Subject: [PATCH] =?UTF-8?q?FABRIC.md:=20correct=20=C2=A717.7's=20stadium?= =?UTF-8?q?=5Fadmit()=20cost=20claim=20--=20free=20list=20already=20O(1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3d73b8e described stadium_admit()'s O(N) scans as the typical cost, sourced from item 3.5's commit note written before item 3.7 landed the per-VM free lists. Reading stadium.c:312-381 directly: the free-list pop is the primary path (O(1), no scan), and the fallback scan only triggers once a VM's own floor is full, scoped to that VM's residents only, never the global array. Option B is better justified than originally written, not just corrected. Co-Authored-By: Claude Sonnet 5 --- FABRIC.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/FABRIC.md b/FABRIC.md index d38dd27..5ea0965 100644 --- a/FABRIC.md +++ b/FABRIC.md @@ -1143,16 +1143,17 @@ resolves four of the five questions this section left open: resident — `execution_heat` stays fully inert, matching the rule as already committed. **Chosen: (B).** - **Accepted cost, not a new gap:** `stadium_admit()` (item 3.5, `DONE`) already documents - its own two full-array scans as O(N), deferred until the free list lands (`FABRIC.md - :2971-2974`, "not worth a workaround for code with no caller yet"). Option B calls that - O(N) path on every dispatch of every non-resident word — the same "check on every touch" - shape the old hot-words cache already used (`hotwords_cache_lookup()` in the word-lookup - path, §17.3), but each check costs O(N) here instead of the old cache's O(1) - threshold-plus-round-robin-write. This is deliberately paid for now, in exchange for - keeping `execution_heat` inert, and is expected to resolve the same way item 3.5's own - scans do — when the free list (item 3.7's per-VM free-list heads) replaces the full-array - scan. Not a new item; it collapses into item 3.5's already-recorded debt. + **Correction (2026-08-05): the cost below was stated wrong.** An earlier draft of this + paragraph took item 3.5's own commit note — written before item 3.7 — at face value + instead of reading `stadium_admit()` as it stands today (`stadium.c:312-381`). The free + list landed with item 3.7 and **is the primary path**: an O(1) pop, no scan, no + comparison. The O(N) fallback only runs once a VM's own free list is exhausted, and even + then it scans only that VM's own resident cells (`stadium_owner[i] != slot`), never the + global array. Option B is O(1) in the common case — every admission attempt, for as long + as the touched VM's Stadium floor has free capacity — and only degrades once that VM's + floor is genuinely full, which is exactly when a real ranking decision (not a workaround) + is the correct thing to be paying for. Better-justified than the original draft, not + merely corrected. 4. ~~**What happens to `dict_hash` and parity comparisons that predate this change.**~~ **RESOLVED by #2 above** — nothing predates a change that isn't being made to the hashed field.