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}");
}