#45 ROOT CAUSE + FIX: the gauge executive starves in MP -- panels froze at healthy fps
Instruments repaint via the background task pump, which authentically runs
ONLY in the frame's leftover time with a floor of ONE pump per frame; the
gauge renderer is 1 of ~7 round-robin tasks and each turn advances ONE gauge
of ~140 active, with the rate mask advancing once per full sweep. On a busy
MP mission the foreground eats the whole frame budget, the floor becomes the
norm, and the whole instrument stack rotates once in MINUTES at perfect fps:
comms-panel K/D stuck at 0, recharge tickers frozen, while the tallies and
their replication underneath were exactly right. Measured: 4-node bench at
70-90 fps gave the PilotList ~2 Execute turns in six minutes.
Fix, both env-tunable, authentic behavior restorable:
BT_BG_MIN (APPMGR.cpp, default 32, 0=authentic) minimum background
pumps per frame regardless of slack;
BT_GAUGE_BATCH (GAUGREND.cpp, default 32, 1=authentic) gauges advanced per
gauge-renderer turn (a visit is only a rate-mask check
unless the gauge is due).
Verified 4-node self-damage bench: sweeps 0.006/s -> 18-20/s, PilotList ~10
Exec/s, ALL FOUR panels tracked every death live (0->11) within ~1s, bg cost
2-4 ms/frame, respawn ledger clean (40 cycles, 0 swallow / 0 mismatch).
Also: BT_PERF now reports gaugeTurns/sweeps/active alongside bgTasks;
BT_AF_PERIOD now throttles the missile autofire group too (unthrottled spam
trips the documented FailureHeat all-weapons brick, which froze run 1 of the
cross-fire bench).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
bfa1b04990
commit
494f32efb4
@@ -682,6 +682,23 @@ BitMap-strip lamp drew `SetColor(0)` + `DrawBitMapOpaque(0,…)` = invisible. Hi
|
||||
Also corrected: @004c552c is OneOfSeveralStates' **Execute** override (clamp ≥0, chain base),
|
||||
not `BecameActive` — vtable-diffed.
|
||||
|
||||
## The gauge EXECUTIVE — why panels froze in MP, and the fix (#45 root, 2026-07-30) [T0 engine / T2 verified]
|
||||
Instruments repaint via the BACKGROUND task pump (`APPMGR.cpp RunMissions`): after sim+render, the
|
||||
loop pumps `BackgroundTasks::Execute()` (ONE task per pump, ~7 tasks round-robin: net, events,
|
||||
audio, GAUGES, …) **only until the frame deadline** — the gauge renderer's turn advances **one
|
||||
gauge** of the active list (`ProcessOneActiveGauge`, ~140 active), and the 16-bit `GaugeRate`
|
||||
mask advances once per FULL sweep (so "rate D = every 4th frame" is really every 4th SWEEP).
|
||||
On a busy MP mission the foreground eats the whole frame budget → 1 pump/frame → a full
|
||||
instrument rotation took MINUTES at perfectly healthy fps: comms-panel K/D stuck at 0, recharge
|
||||
tickers frozen — while the underlying tallies (and their replication) were exactly right. This
|
||||
is the real root of the field "panels don't update in MP" (#45's display half).
|
||||
**Fix (both env-tunable):** `BT_BG_MIN` (APPMGR.cpp, default 32, 0=authentic) guarantees a
|
||||
minimum pump floor per frame; `BT_GAUGE_BATCH` (GAUGREND.cpp, default 32, 1=authentic) advances
|
||||
a batch of gauges per gauge turn (a visit is only a rate-mask check unless due). Verified
|
||||
4-node: sweeps 0.006/s → **18-20/s**, PilotList ~10 Exec/s, all four panels tracked every death
|
||||
within ~1s, bg cost 2-4 ms/frame. Diagnostics: `BT_PERF=1` → `[perf] … bgTasks/gaugeTurns/
|
||||
sweeps/active` 1 Hz (APPMGR.cpp); `[score] panel DRAW` edge log (btl4gau3.cpp, BT_SCORE_LOG).
|
||||
|
||||
## Key Relationships
|
||||
- Full history: `docs/GAUGE_COMPOSITE.md`; reticle recovery: `phases/phase-02-dpl2d-reticle.md`.
|
||||
- Uses: [[attribute-pointer]] + [[reconstruction-gotchas]]; reads [[subsystems]] state.
|
||||
|
||||
@@ -761,6 +761,18 @@ register. ⚠ The audit also flags the damage-economy item as SELF-CONTRADICTOR
|
||||
numbers no longer point at that code).
|
||||
|
||||
## Multiplayer (Phase 7 / P6)
|
||||
- **Cross-fire bench opens (2026-07-30, first real-weapons 4-node runs).** (a) COMBAT STALL: all
|
||||
firing and dying ceased ~3 min in (run 2, throttled `BT_AF_PERIOD=7`) with everyone alive,
|
||||
subsystems healthy, and fps fine — engagement/heat state needs a logging pass (`BT_GOTO_LOG`
|
||||
+ heat probes); run 1's max-spam stall was the documented FailureHeat all-weapons brick.
|
||||
(b) NODE CRASH: one instance died silently mid-run (no SEH line, no WER record; last log line
|
||||
= audio census; yesterday's WER archive holds 3× `OpenAL32.dll` abort `0x40000015` and WER
|
||||
dedups repeats — suspect the audio-pool thread). procdump harness now wired into
|
||||
`scratchpad/night6/mp4_cross.sh`; did NOT recur under throttled fire. (c) VERIFIED GOOD: 4
|
||||
deaths ↔ 4 kills credited to the right shooters (incl. a mutual kill), `NOCREDIT`=0, cross-
|
||||
machine damage applied on victims' masters with correct attribution; one kill credit arrived
|
||||
17 s late (`SCORE type=2`) — the deferred ScoreMessage reroute path, watch it.
|
||||
|
||||
- **Gitea #12 MP incident (2026-07-19) — root causes found; BOTH FIXES LANDED 2026-07-19
|
||||
(awaiting the human MP death-and-survive verification).** Findings [T1/T2 — see the #12
|
||||
comments + `scratchpad/incident_2157/`]:
|
||||
|
||||
Reference in New Issue
Block a user