diff --git a/context/multiplayer.md b/context/multiplayer.md index 2c6ef3d..3922196 100644 --- a/context/multiplayer.md +++ b/context/multiplayer.md @@ -437,6 +437,18 @@ phase). Plan: `~/.claude/plans/partitioned-snuggling-piglet.md`. from take 2's commit is UNPROVEN -- the measured fact is just that loads outlive any fixed cap; the counter design is correct under either reading. Residual: WHY loads take 1-2+ min on the operator box (vs ~30s earlier same day) is an open perf question ([loadobj] timings). +- **WHERE THE LOAD MINUTE GOES (2026-07-22) [T2, measured]**: teal->green (egg receipt -> + WaitingForLaunch/READY) measured 58s on the operator box uncontended, ~28s on a quieter run. + Attribution (loadphase markers + queue dump): renderer LoadMission = **31ms**, model loads = + **0.2s** -- essentially ALL the time is the LoadingMission ready-gate + (`CheckLoadMessageHandler` requires `IsPriorityEmpty(MinEventPriority)`, which counts TIMED + events too) waiting out the **three renderers' entity-make streams**: every entity/subsystem + creation posts a make message (message 3) to each Renderer receiver (classIDs 8/30/36 = + video/audio/gauge), hundreds deep per queue, draining over the whole window (the audio + renderer's share is why sound starts mid-load). Optimization (batch the makes / profile + per-event cost) is an OPEN perf item -- deliberately not attempted pre-8-player-night. + Diags: `[loadphase]` markers always on; the full queue dump gates on `BT_LOAD_DIAG=1`; + `GeneralEventQueue::DumpBlockers` + the named fallback in `Event::DumpData`. - **READY LIGHT (2026-07-22) [T2, live-verified]**: the roster showed "registered" for a still-loading pod and a ready one alike. When the app ladder reaches WaitingForLaunch (APP.cpp CheckLoad transition) the pod sends ONE empty route **-10** frame on its live relay diff --git a/engine/MUNGA/APP.cpp b/engine/MUNGA/APP.cpp index c42825e..22a3e0f 100644 --- a/engine/MUNGA/APP.cpp +++ b/engine/MUNGA/APP.cpp @@ -1377,9 +1377,17 @@ void static int s_busy_passes = 0; ++s_busy_passes; if ((s_busy_passes % 5) == 1) + { DEBUG_STREAM << "[loadphase] CheckLoad: event queue still busy" << " (pass " << s_busy_passes << ") t=" << GetTickCount() << std::endl << std::flush; + // full queue dump is VERBOSE (hundreds of lines per load) -- + // finding of record: the blockers are the three renderers' + // entity-make streams (message 3 for Renderer, classIDs + // 8/30/36) -- re-enable to re-verify + if (getenv("BT_LOAD_DIAG") != NULL) + eventQueue->DumpBlockers(MinEventPriority); + } } if (eventQueue->IsPriorityEmpty(MinEventPriority)) { diff --git a/engine/MUNGA/EVENT.cpp b/engine/MUNGA/EVENT.cpp index 1ce56e0..7d40221 100644 --- a/engine/MUNGA/EVENT.cpp +++ b/engine/MUNGA/EVENT.cpp @@ -295,7 +295,9 @@ void else { Vanilla_Message: - DEBUG_STREAM << "Message " << messageToSend->messageID << " for object of classID " << target->GetClassID() << std::endl << std::flush; + DEBUG_STREAM << "Message " << messageToSend->messageID << " for " + << (target->GetDerivation() ? target->GetDerivation()->className : "?") + << " (classID " << target->GetClassID() << ")" << std::endl << std::flush; } } @@ -718,6 +720,31 @@ Logical return !i.GetCurrent() && !j.GetCurrent(); } +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::DumpBlockers(int priority) +{ + Check(this); + Verify(priority >= 0 && priority < priorityLevels); + ChainIteratorOf pending(this[priority].pendingEvents); + AbstractEvent *event; + while ((event = pending.GetCurrent()) != NULL) + { + DEBUG_STREAM << "[loadphase] pending: " << std::flush; + event->DumpData(); + pending.Next(); + } + ChainIteratorOf timed(this[priority].timedEvents); + while ((event = timed.GetCurrent()) != NULL) + { + DEBUG_STREAM << "[loadphase] timed(+" + << (float)(event->alarmTime - Now()) << "s): " << std::flush; + event->DumpData(); + timed.Next(); + } +} + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical diff --git a/engine/MUNGA/EVENT.h b/engine/MUNGA/EVENT.h index fe66219..096fdf7 100644 --- a/engine/MUNGA/EVENT.h +++ b/engine/MUNGA/EVENT.h @@ -230,6 +230,11 @@ public: Logical IsPriorityEmpty(int priority); + // LOAD-ATTRIBUTION DIAG (2026-07-22): name every event holding a + // priority level non-empty (the LoadingMission ready-gate blocker hunt). + void + DumpBlockers(int priority); + Logical ProcessOneEvent(int min_priority=0); void