docs(performance): detail Slice H execution gates

This commit is contained in:
Erik 2026-07-25 05:05:40 +02:00
parent 51e184725f
commit c0bec56dfe
2 changed files with 175 additions and 0 deletions

View file

@ -0,0 +1,169 @@
# Modern runtime Slice H execution plan
**Status:** ACTIVE
**Parent plan:** `2026-07-24-modern-runtime-architecture.md`, Slice H
**Prerequisite state:** Slice G4 production cutover is automated-gated; its
user visual gate remains pending.
## 1. Safety boundary
Slice H removes work which scales with presentation rate. It does not change
retail gameplay rules, visible-cell authority, light membership, packet
ordering, acknowledgement timing, heartbeat placement, or UI presentation.
The G4 old-route referee remains available until the user accepts the visual
gate. Slice H must not delete or alter that rollback boundary.
If the G4 visual result is wrong, revert only:
```text
git revert ef1d263337997bb030eadb7b8e71d73dc659907a
```
Do not reset history and do not revert G3. The portal-warmup corrections
`129dd77d` and `03b10183` are independent of the retained draw-source cutover.
## 2. H-a — retained UI, live attachments, diagnostics, and frame scratch
### H-a1 — cached shaped text
1. Add a small retained text-layout cache keyed by source revision/value plus
width, padding, color, and font identity.
2. Convert appraisal item, inscription, spell, creature, character-info, and
active-effect detail providers so expensive report construction and
wrapping occur only after source or layout changes.
3. Preserve `UiText.LinesProvider` as the rendering seam. Dynamic one-line
widgets remain dynamic; this change is limited to report/wrapped content.
4. Ensure selection, appraisal response, component count, enchantment,
character-property, font, and resize changes invalidate the right cache.
5. Add tests proving stable draws return the same line collection while source
and geometry changes rebuild it.
Gate: the existing appraisal/character/effect behavior tests remain unchanged,
and repeated stable provider polls allocate no report/wrap objects.
### H-a2 — visible cooldown participants
1. Keep the shared retail heartbeat and one cooldown result per represented
item.
2. Index mounted `UiItemList` participants once at bind time.
3. At heartbeat, visit only lists whose complete ancestor chain is visible.
Hidden panels keep no stale visual state: their slots query zero while
hidden and are refreshed on the first visible heartbeat.
4. Keep future-slot support and shared-group behavior.
Gate: hidden inventory, equipment, external-container, vendor, and spell-bar
lists are not scanned; reopening immediately displays the authoritative
cooldown step.
### H-a3 — equipped-child transition work
1. Preserve both frame ordering points: pre-network presentation and
post-network spatial reconciliation have different authority boundaries.
2. Split transition retry from pose recomposition.
3. Run the complete parent-first pose walk once after animation.
4. In the post-network phase, recompose only attachments dirtied by accepted
root/relation/appearance changes.
5. Replace mutation-safe dictionary `ToArray` snapshots with retained key
scratch buffers. Callback reentrancy still observes the same transition
generation checks.
Gate: equip, unparent, reparent, pose loss, rollback, delete, GUID reuse, and
subtree-withdrawal suites preserve exact event and resource counts.
### H-a4 — diagnostics and frame scratch
1. Reuse one synchronous `RetailPViewFrameInput` owned by
`WorldSceneRenderer`; reset every field before each draw.
2. Expose stable borrowed landblock entry/bounds views instead of creating
iterator state in each frame.
3. Consumer-gate diagnostic landblock visibility counting and shadow
enumeration. When no DebugVM/collision/probe consumer exists, publish a
neutral diagnostic outcome without scanning resident landblocks.
4. Do not rework `InteriorEntityPartition` while the G4 referee remains.
Issue #241 closes with G5 old-route deletion, not by editing the fallback.
5. Profile capped and uncapped production paths and retain evidence.
Gate: identical framebuffer/scene digest, no per-frame PView input allocation,
and no diagnostic world traversal with all consumers disabled.
## 3. H-b — exact light top-k
Retail anchors:
- `CEnvCell::add_dynamic_lights` at `0x0052D410`
- `Render::insert_light` at `0x0054D1B0`
- `Render::add_dynamic_light` at `0x0054D420`
- global caps at `0x0081EC94` / `0x0081EC98`
Execution:
1. Preserve the resident `_all` registry and existing visible-cell filter.
2. Preserve dynamics-first ordering and squared distance from the player.
3. Replace only the over-cap complete sort with a bounded exact top-k
selection.
4. Define tie-breaking from the existing comparator so the selected set and
final submission order are identical, including equal-distance fixtures.
5. Differential-test randomized candidate sets and the captured 463-light Town
Network fixture against the old full-sort oracle.
6. Run the fixed-camera screenshot comparison and connected light gate.
Gate: identical selected IDs and submission order for every fixture, identical
Town Network screenshot, reduced overflow CPU/allocation, and AP-85 retired
only after the visual evidence passes.
## 4. H-c — ordered, allocation-conscious network I/O
Retail/transport invariants:
- one outstanding receive;
- kernel datagram arrival order remains inbound queue order;
- one acknowledgement decision per accepted packet;
- `LinkStatusHolder::OnHeartbeat` at `0x004113D0` remains at the same
last-heard point;
- `PumpOnce` handshake pacing remains unchanged;
- fragmented message assembly and sequence gates remain authoritative.
Execution:
1. Capture allocation and ordering baselines for login, idle, motion, portal,
appraisal, container, and combat traffic.
2. Introduce a single cancellable socket receive owner using reusable/pool
storage.
3. Decode packet headers and fragments from spans/borrowed storage.
4. Copy only payloads whose lifetime crosses the receive/dispatch boundary;
pooled receive memory is never returned while referenced.
5. Replace outbound temporary arrays with span/list segment writes where the
socket API permits.
6. Prove cancellation, remote close, malformed packet, receive fault, fragment
reassembly, queue backpressure, and reconnect cleanup.
7. Run connected lifecycle, reconnect, portal, interaction, and soak gates.
Gate: identical decoded event/ack traces, no receive-thread death, no pooled
buffer lifetime violation, and materially reduced bytes per packet.
## 5. Commit and evidence order
Each numbered unit lands as a bisectable commit after focused tests, App
Release, complete Release, and documentation reconciliation:
1. H-a1 cached shaped text.
2. H-a2 cooldown visibility.
3. H-a3 attachment retry/recomposition.
4. H-a4 diagnostics/frame scratch.
5. H-b exact light top-k.
6. H-c network receive/decode/send allocations.
7. Slice-H connected measurements and closeout.
Raw captures stay under `.test-out/` or `logs/`; reviewed summaries and compact
fixtures are committed under `docs/research/` or the matching test project.
## 6. Deferred boundaries
- Physics `Transition` pooling (#237) remains Slice I and requires reset-
completeness/identity tests first.
- G5 old-route/referee deletion waits for the user's G4 visual acceptance.
- Static publication indexing (#242) is not silently folded into H; it is
measured after H-a and scheduled only if still material.
- Slices IL start only after Slice H is measured and documented, but no
additional authorization is required.