docs(opstack): handoff -- 001 chains into 002, and PERF is now aimed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 15:46:30 +02:00
parent 7313201e91
commit 7909c4f2ca
+39 -15
View File
@@ -95,19 +95,29 @@ collision**. The warning is written at the site you land on when you add one.
`|AB| ≥ K`, so the running minimum saturates at `K` below the smallest term. Without that `|AB| ≥ K`, so the running minimum saturates at `K` below the smallest term. Without that
observation the slack would scale with the ~88 tunnels in a cache and the criterion would be dead.) observation the slack would scale with the ~88 tunnels in a cache and the criterion would be dead.)
## First actions — one build to read, one task to hand Codex ## First actions — one build to read, two tasks to hand Codex
### (a) Hand Codex `CODEX-TASK-001-tile-skip-stats.md` — this is the priority ### (a) Hand Codex `CODEX-TASK-001-tile-skip-stats.md`, then `-002-` — 001 first, they chain
Everything in this refactor has been proved in an automation harness on 40 sampled tiles, and Everything in this refactor has been proved in an automation harness on 40 sampled tiles, and
**nothing has ever been observed in the running game.** The task adds a `stat VoxelForge` group with **nothing has ever been observed in the running game.** Task 001 adds a `stat VoxelForge` group with
`TilesClassified / TilesSkippedAllSolid / TilesSkippedAllAir / TilesMeshed`. `TilesClassified / TilesSkippedAllSolid / TilesSkippedAllAir / TilesMeshed`, **plus
`TilesOpStackSolid / TilesOpStackAir` at a second site**. Task 002 adds `ColumnMemoHit / Miss` to the
same group; it needs 001's header to exist, and both should land in one build.
Its deliverable is a **before/after that constitutes the production proof of T1.d**: with no strate Its deliverable is a **before/after that constitutes the production proof of T1.d**: after ticking
opted in, `TilesSkippedAllSolid` underground must read **0**; after ticking `bUseOperatorStack` on `bUseOperatorStack` on one `TunnelNetwork` strate and flying the same route, **`TilesOpStackSolid`
one `TunnelNetwork` strate and flying the same route, it must be **non-zero**. The spec carries the must go non-zero**. The spec carries the invariants — most importantly that `bTrivialEmpty` decides
invariants — most importantly that `bTrivialEmpty` decides whether a tile has **collision**, and that whether a tile has **collision**, and that `GenerateTileResult` runs on **worker threads** so a plain
`GenerateTileResult` runs on **worker threads** so a plain `static int32++` is a data race. `static int32++` is a data race.
⚠️ **Corrected 2026-08-16 — the earlier version of this bar was unmeasurable.** It said
`TilesSkippedAllSolid` would read 0 underground with no strate opted in. It will not: `ClassifyTile`
also proves `AllSolid` on its **hand-written** path (a bedrock-gap chunk sets `bCanAir = false`,
`VoxelGenerator.cpp` ~2835), which fires with nothing ticked at all. That is the same "~84 %" caveat
below, which the old bar quoted and then contradicted. The op-stack-only counters are zero **by
construction** — the cave branch returns `Mixed` at `UsesOperatorStackForChunk` — so they are the
ones that prove anything.
Interim answer if Jahni wants it before that lands: **Unreal Insights already shows this.** The trace Interim answer if Jahni wants it before that lands: **Unreal Insights already shows this.** The trace
scopes `VoxelForge_ClassifyTile` and `VoxelForge_GenerateMesh` exist at the site; a skipped tile is a scopes `VoxelForge_ClassifyTile` and `VoxelForge_GenerateMesh` exist at the site; a skipped tile is a
@@ -135,12 +145,26 @@ Everything before it is built and green.
## Then, in order ## Then, in order
1. **PERF — still unparked, and now the biggest open item.** The op path is measurably slower. One 1. **PERF — the biggest open item, and now AIMED (2026-08-16). Read this before touching it.**
cause found and fixed (the column memo discarded itself every chunk). Remaining suspects in order: The op path is measurably slower; one cause was already found and fixed (the column memo
the hashed column lookup vs `GSurfColCache`'s direct-indexed box, then per-voxel virtual dispatch. discarded itself every chunk). Three things were worked out since, all still **unmeasured**:
Also measured and stated: the gate is tested twelve times per voxel instead of once (stage B5's
deliberate trade). **Measure before optimising** — that is the §C10 lesson, and this session - **The A/B needs no new code.** `VoxelForge_ClassifyTile` and `VoxelForge_GenerateMesh` already
re-learned it the hard way. exist, and the world is deterministic, so two Insights traces — flag off, then on, same seed and
route — are a clean before/after.
- **But it is unreadable without task 001.** With the stack on, tiles get *skipped*, so
`GenerateMesh` runs fewer times; a total conflates "cheaper per tile" with "fewer tiles" and
those pull opposite ways. `TilesMeshed` is the denominator. **⇒ 001 is a PREREQUISITE here, not
a parallel item.** Order: 001 → traces → attribution → fix.
- **The suspects don't share an archetype**, so measure one ticked strate at a time.
*SurfaceWorld* = the hashed column memo. *TunnelNetwork* = **19 virtual calls per voxel**
(16 from `BuildTunnelNetworkStack` + 3 from `AppendStructuralPost`), plus the known 12× gate
re-test (stage B5's deliberate trade).
`CODEX-TASK-002` tests the SurfaceWorld suspect and **fixes nothing on purpose** — the derivation
says the direct-mapped 4096-slot table evicts ~25 % of columns *every Z plane* (the mesher
pre-samples **Z-outermost**), for a derived ~9× on column work. **Derived, not measured.**
**Measure before optimising** — the §C10 lesson, re-learned the hard way last session.
2. **The warp squeeze — PARKED with its ceiling measured, my recommendation is leave it.** The 2. **The warp squeeze — PARKED with its ceiling measured, my recommendation is leave it.** The
`WARP SHARE` line says over half the remaining blocking is the query-box dilation, not geometry `WARP SHARE` line says over half the remaining blocking is the query-box dilation, not geometry
(production: rooms 0.9 → 0.4, tunnels 2.4 → 1.1 with the dilation zeroed). The only remaining (production: rooms 0.9 → 0.4, tunnels 2.4 → 1.1 with the dilation zeroed). The only remaining