Table of Contents

Struct TickTelemetry

Namespace
Typhon.Engine
Assembly
Typhon.Engine.dll

Per-tick telemetry snapshot. Recorded at the end of each tick into the TickTelemetryRing.

public struct TickTelemetry
Inherited Members

Fields

ActiveSystemCount

Number of systems that actually executed (not skipped) this tick.

public int ActiveSystemCount

Field Value

int

ActiveWorkerCount

Number of worker threads active during this tick.

public int ActiveWorkerCount

Field Value

int

ActualDurationMs

Actual wall-clock tick execution time (reset → completion), in milliseconds.

public float ActualDurationMs

Field Value

float

CurrentLevel

Current overload response level for this tick.

public OverloadLevel CurrentLevel

Field Value

OverloadLevel

EventQueueDepth

Total pending events across all event queues at tick end. Sustained growth indicates backlog.

public int EventQueueDepth

Field Value

int

LostWakes

Lost wakes caught this tick: a parked worker's between-tick backstop (50 ms) fired after a dispatch whose Set never reached it. Non-zero means the wake protocol is broken; zero does not prove it is not, since a lost wake that the next dispatch's Set rescues before the backstop leaves nothing to count. Counted when caught, so a wake lost late in one tick lands in the next. Cumulative: LostWakeCount.

public int LostWakes

Field Value

int

OverrunRatio

Ratio of actual to target duration. Values > 1.0 indicate overrun. Used by overload management (#201) to detect sustained overruns.

public float OverrunRatio

Field Value

float

TargetDurationMs

Target tick duration based on BaseTickRate (e.g., 16.67ms at 60Hz).

public float TargetDurationMs

Field Value

float

TickIntervalMs

Actual tick-to-tick interval in milliseconds (time from previous tick start to this tick start). This is the true period seen by the simulation. Compare against TargetDurationMs to measure jitter: |TickIntervalMs - TargetDurationMs|. Zero for the first tick.

public float TickIntervalMs

Field Value

float

TickMultiplier

Tick rate multiplier (1 = normal, 2+ = modulated under Level 3).

public int TickMultiplier

Field Value

int

TickNumber

Monotonically increasing tick number (0-based).

public long TickNumber

Field Value

long

TotalEntitiesDeferred

Total entities deferred (budget-capped) across all systems this tick. Zero until Level 2 enforcement.

public int TotalEntitiesDeferred

Field Value

int

TotalEntitiesProcessed

Total entities processed across all systems this tick.

public int TotalEntitiesProcessed

Field Value

int

UowFlushMs

Wall-clock time this tick spent in the Unit-of-Work flush, in milliseconds — which in WAL mode is WalManager.RequestFlush followed by WaitForDurable, i.e. the tick's DURABILITY WAIT (#CLI-04).

public float UowFlushMs

Field Value

float

Remarks

A wall-clock span, not CPU, and not a per-commit figure. The tick driver blocks here until the WAL writer has published the tick's records, so this is the latency a tick pays for durability. The per-COMMIT wait is a different population: it is measured inside WalWriter.WaitForDurableSlow, has no always-on accumulator, and its fast path (already durable) returns without touching a timer at all. A consumer reporting this as typhon.durability.wait.p99 must say which of the two it means.

Why here rather than on a profiler span. The flush is already wrapped in a TickPhase.UowFlush span, but a span exists only while the profiler is recording: with the profiler off the wrapper folds away and the number does not exist, which is exactly why the metric emitted a hard zero before this field. The ring is single-writer from the tick driver and stamped at tick end, so carrying it here costs one Stopwatch pair per tick — on a path that just waited on an fsync — and no synchronisation at all.

Zero is a real reading: a tick whose records were already durable, or one that committed nothing, genuinely waited for nothing. It is not "unknown". (It is also zero for a tick that did not reach its flush at all — see the clear at the top of the scheduler's tick driver, which is what keeps a failed flush from donating its wait to the next tick.)