using System.Diagnostics; using AcDream.Runtime; namespace AcDream.App.Streaming; /// /// ACDREAM_PROBE_REVEAL_TIMING=1 (see /// ): wall-clock /// attribution of one login/portal hold. Emits [reveal-timing] lines: /// /// /// event=begin — the hold starts, with the required window and /// its landblock count. /// event=render-ready / composites-ready / collision-ready / /// gate-ready / materialized — first-true edges with elapsed ms. The /// readiness barrier OBSERVES the dimensions serially (composites are only /// evaluated once render is ready, collision once both are), so each edge's /// delta over the previous one is that dimension's observed TAIL, not its /// total concurrent cost — the progress lines carry the concurrency /// shape. /// 1 Hz progress — elapsed, the three flags, and the resident /// landblock count, so a budget-paced linear drip is visually obvious in the /// log. /// SUMMARY once at the viewport reveal — the per-edge /// timeline on one line. /// /// /// Diagnostic-only: never constructed unless the probe env is set, changes /// no behavior, and costs one branch per Evaluate poll otherwise. /// internal sealed class RevealTimingProbe { private readonly Func? _loadedLandblockCount; private readonly Stopwatch _clock = new(); private long _generation; private string _kind = ""; private int _windowLandblocks; private bool _render; private bool _composites; private bool _collision; private bool _gateReady; private bool _materialized; private bool _summarized; private long _renderMs = -1; private long _compositesMs = -1; private long _collisionMs = -1; private long _gateReadyMs = -1; private long _materializedMs = -1; private long _lastProgressMs; public RevealTimingProbe(Func? loadedLandblockCount) => _loadedLandblockCount = loadedLandblockCount; public void Begin( string kind, long generation, uint destinationCell, in StreamingRevealWindow window) { _generation = generation; _kind = kind; int side = window.FarRadius * 2 + 1; _windowLandblocks = side * side; _render = false; _composites = false; _collision = false; _gateReady = false; _materialized = false; _summarized = false; _renderMs = -1; _compositesMs = -1; _collisionMs = -1; _gateReadyMs = -1; _materializedMs = -1; _lastProgressMs = 0; _clock.Restart(); Console.WriteLine( $"[reveal-timing] event=begin kind={kind} gen={generation} " + $"cell=0x{destinationCell:X8} window={window.NearRadius}/" + $"{window.FarRadius} landblocks={_windowLandblocks} " + $"loaded={_loadedLandblockCount?.Invoke() ?? -1}"); } public void Observe( in WorldRevealReadinessSnapshot readiness, in RuntimePortalSnapshot portal) { if (_generation == 0 || portal.Generation != _generation) return; long elapsed = _clock.ElapsedMilliseconds; if (!_render && readiness.IsRenderNeighborhoodReady) { _render = true; _renderMs = elapsed; Edge("render-ready", elapsed); } if (!_composites && readiness.AreCompositeTexturesReady) { _composites = true; _compositesMs = elapsed; Edge("composites-ready", elapsed); } if (!_collision && readiness.IsCollisionReady) { _collision = true; _collisionMs = elapsed; Edge("collision-ready", elapsed); } if (!_gateReady && readiness.IsReady) { _gateReady = true; _gateReadyMs = elapsed; Edge("gate-ready", elapsed); } if (!_materialized && portal.Materialized) { _materialized = true; _materializedMs = elapsed; Edge("materialized", elapsed); } if (!_summarized && portal.WorldViewportObserved) { _summarized = true; Console.WriteLine( $"[reveal-timing] SUMMARY kind={_kind} gen={_generation} " + $"totalMs={elapsed} renderMs={_renderMs} " + $"compositesMs={_compositesMs} collisionMs={_collisionMs} " + $"gateReadyMs={_gateReadyMs} " + $"materializedMs={_materializedMs} " + $"landblocks={_windowLandblocks}"); return; } if (!_summarized && elapsed - _lastProgressMs >= 1000) { _lastProgressMs = elapsed; Console.WriteLine( $"[reveal-timing] elapsedMs={elapsed} " + $"render={(_render ? 1 : 0)} " + $"composites={(_composites ? 1 : 0)} " + $"collision={(_collision ? 1 : 0)} " + $"loaded={_loadedLandblockCount?.Invoke() ?? -1}" + $"/{_windowLandblocks}"); } } private void Edge(string name, long elapsed) => Console.WriteLine( $"[reveal-timing] event={name} kind={_kind} gen={_generation} " + $"elapsedMs={elapsed} " + $"loaded={_loadedLandblockCount?.Invoke() ?? -1}" + $"/{_windowLandblocks}"); }