From d4f6b7bf03f916c909148f96cd8a7de77ceb8363 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Mon, 24 Aug 2026 19:13:06 +0000 Subject: [PATCH] re: freezes are stochastic, not eliminated; calibration vectorised Correcting the previous iteration's wording. It claimed on n=1 that disabling the periodic rescan "removes the freeze". With more runs that is too strong: the configuration is now clean at 210, 240 and 300 seconds and frozen at 60 on a fourth run. The tally across configurations: the heavy probe froze at 27, 45, 83, 183 and 255 seconds; the cheap probe with a 90 s rescan froze at 183; the cheap probe with no rescan is clean in three runs of four past 200 s. That is a real and large improvement in survival, but it is a change in probability rather than a fix, and the documentation now says so. The witness handled the frozen run correctly -- losses stop at t=45 and stalls are flagged from t=60 onward, with no contradiction between them. Separately, the candidate search was the last Python loop over eight million words and most of the remaining startup cost. Replaced with two numpy vector operations; 7250 candidates found and startup is no longer the bottleneck. Boot now dominates: about 190 s of title movie plus 35 s to flight against a 595 s turn cap leaves roughly 350 s of observation, so boot is the only remaining lever if longer windows are needed. Practical rule recorded: do not treat a single frozen run as evidence. Run, check the witness, discard the frozen ones and keep the clean ones -- about three in four are usable now, which is workable where it previously was not. --- docs/re/BACKLOG.md | 9 +++++--- docs/re/guest-stalls.md | 37 +++++++++++++++++++++++++++++++++ tools/re-capture/wave7_probe.py | 17 ++++++++++----- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 520034f..5a52dc4 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -454,9 +454,12 @@ search cannot find a *schedule*. 90 s, and the new calibration added **two more 32 MB reads** — the 45 s freeze came right after it. 🔴 **The trim BROKE the witness** (17 candidates, `0/17` on every sample of a run with 13 losses) — reverted; two 32 MB reads once at - startup is the price of a working witness. ✅ **Instead, disabling the periodic - rescan removed the freeze**: first fully clean probed run, **zero stalls over - 210 s** with 8 losses, ended by the turn timeout not a freeze (n=1). The rescan + startup is the price of a working witness. ✅🟡 **Instead, disabling the periodic + rescan LARGELY removes the freeze** — corrected from "removes" after more runs: + clean at 210/240/300 s but **frozen at 60 s** on a fourth. Tally — heavy probe + froze at 27/45/83/183/255 s; cheap+rescan at 183 s; cheap, no rescan: 3 of 4 + clean past 200 s. A large probability improvement, **not a fix**. Practical + rule: run, check the witness, discard frozen runs (~3 in 4 usable). The rescan existed only to catch newly-allocated craft, which the roster work showed never happens. * ✅ **Run 16: the first TRUSTWORTHY negative.** Validated witness, no stall on diff --git a/docs/re/guest-stalls.md b/docs/re/guest-stalls.md index ec1a7ae..294c68c 100644 --- a/docs/re/guest-stalls.md +++ b/docs/re/guest-stalls.md @@ -376,3 +376,40 @@ clean no-probe control it points clearly at recurring heavy reads rather than at memory reading as such. The run ended on the turn's timeout, not a freeze. + +--- + +# Freezes are stochastic, not eliminated (2026-08-24) + +The previous entry claimed disabling the periodic rescan "removes the freeze" on +n = 1. With more runs that is too strong. The tally: + +| configuration | freeze onset | +|---|---| +| heavy probe | 27, 45, 83, 183, 255 s | +| cheap probe + 90 s rescan | 183 s | +| **cheap probe, no rescan** | clean 210 s, clean 240 s, clean 300 s, **frozen at 60 s** | + +Three of four runs now survive past 200 s where essentially none did before, so +removing the rescan is a **real and large improvement** — but it is a change in +probability, not a fix, and the wording is corrected accordingly. + +The witness handled the frozen run correctly: losses stop at t = 45 s, stalls are +flagged from t = 60 s onward, no contradiction. + +## ✅ Calibration is no longer the bottleneck + +The candidate search was the last Python loop over 8 million words. Replaced with +two numpy vector operations (`AGENT.md` notes numpy is installed, and its absence +used to look like a logic bug). 7250 candidates found, and the startup cost is +now small enough that **boot dominates**: ~190 s of title movie plus ~35 s to +flight, against a 595 s turn cap, leaves roughly 350 s of observation. + +Boot is now the binding constraint on how much game time one turn can see, and +it is the only remaining lever worth pulling if longer windows are needed. + +## Practical consequence + +Do not treat a single frozen run as evidence of anything. Run, check the witness, +discard the frozen ones, and keep the clean runs — about three in four are usable +now, which is workable where it previously was not. diff --git a/tools/re-capture/wave7_probe.py b/tools/re-capture/wave7_probe.py index c79179b..2504903 100755 --- a/tools/re-capture/wave7_probe.py +++ b/tools/re-capture/wave7_probe.py @@ -126,11 +126,18 @@ def main(): n = min(1 << 24, hiw - pos); out += os.pread(fd, n, pos); pos += n return bytes(out) a = grab(); time.sleep(3.0); b = grab() - cands = [] - for k in range(0, min(len(a), len(b)) - 3, 4): - va, vb = struct.unpack_from('>I', a, k)[0], struct.unpack_from('>I', b, k)[0] - if va < vb and 5 < (vb - va) / 3.0 < 200: - cands.append((lo + k, round((vb - va) / 3.0))) + # The candidate search was the last Python loop over 8 million words and cost + # most of the remaining startup time. numpy does the same comparison as two + # vector ops. (AGENT.md: numpy is installed; its absence used to look like a + # logic bug.) + import numpy as np + n4 = min(len(a), len(b)) // 4 * 4 + A = np.frombuffer(a[:n4], dtype='>u4').astype(np.int64) + B = np.frombuffer(b[:n4], dtype='>u4').astype(np.int64) + d = B - A + rate = d / 3.0 + idx = np.nonzero((d > 0) & (rate > 5) & (rate < 200))[0] + cands = [(lo + int(i) * 4, int(round(float(rate[i])))) for i in idx] # The MODAL cluster is not the frame counter. One run picked a modal rate of # 93/s, and only 11 of 31 of those advanced during active combat -- they are # subsystem counters that tick in bursts. timer_probe measured the frame-rate