WorkerLoadTracker
How busy each worker is, as a fraction of its tick budget: WorkerInfo.TickMs / tickPeriodMs, sampled from every heartbeat and kept for a short window (NebulaConfig.ScaleWindowSeconds).
Nebula · Packages/com.1by3.nebula/Runtime/Orchestrator/WorkerLoadTracker.cspublic sealed class WorkerLoadTrackerHow busy each worker is, as a fraction of its tick budget: WorkerInfo.TickMs / tickPeriodMs, sampled from every heartbeat and kept for a short window (NebulaConfig.ScaleWindowSeconds). The 90th percentile of that window is the scaling signal: a GC spike does not launch a machine, a sustained 80 % does.
The tracker is a plain object with an injected clock, so the scaler can be exercised over synthetic histories without a mesh or Unity time. Samples are kept in a per-worker ring of structs and the percentile is taken from a reused scratch buffer, so a pass allocates nothing once the mesh is warm.
Constructors
WorkerLoadTracker
public WorkerLoadTracker(Func<double> now);| Parameter | Description |
|---|---|
now | Seconds on a monotonic clock. Tests pass their own; the orchestrator passes Unity time. |
Fields
TickPeriodMs
public const float TickPeriodMs = 1000f / NetworkTime.TickRate;One simulated tick's wall-clock budget, in milliseconds (NetworkTime.TickRate).
Percentile
public const float Percentile = 0.9f;Fraction of the window used as "the" utilization of a worker.
WindowSeconds
public float WindowSeconds = 20f;Length of the window each worker keeps, in seconds.
MinSamples
public int MinSamples = 3;How many heartbeats a worker must have inside the window before its utilization means anything. Below this it reads as 0 % busy simply because nothing has been reported yet, and the worker is not considered for retirement (WorkerScaler.IsWarm).
Properties
Count
public int Count { get; }Workers with at least one live sample.
Methods
UtilizationOf
public static float UtilizationOf(float tickMs);Utilization of one tick time, as a fraction of the tick budget (0.5 = half a tick period).
Sample
public void Sample(string workerId, float tickMs);Record one heartbeat's tick time. Repeated identical heartbeats are kept: the window is time-based.
SampleAt
public void SampleAt(string workerId, float tickMs, double at);Record one sample at an explicit time (tests, and replaying a batch of heartbeats).
Expire
public void Expire();Drop samples (and whole workers) older than the window. Called once per pass so a dead worker's history fades.
SampleCount
public int SampleCount(string workerId);How many samples a worker has inside the window right now.
IsWarm
public bool IsWarm(string workerId);Has this worker reported enough to be judged (MinSamples)?
Forget
public void Forget(string workerId);Forget a worker outright (it died or retired).
Utilization
public float Utilization(string workerId);The 90th percentile of a worker's window, or 0 when it has never reported. Nearest-rank on the samples still inside the window, so one bad tick in twenty does not count as the worker's load.
CopyUtilization
public void CopyUtilization(IEnumerable<WorkerInfo> workers, Dictionary<string, float> result);Fill result (cleared first) with the p90 utilization of every worker in workers, including ones with no samples yet (0).
Attribute
public static void Attribute(IReadOnlyDictionary<string, float> workerUtilization, IReadOnlyList<LeaseInfo> leases, IReadOnlyDictionary<string, ContainerLoad> occupancy, in CostWeights weights, Dictionary<string, float> result);Spread each worker's p90 utilization over the containers it leases, in proportion to what CostWeights says their occupants cost. A container nobody reported gets CostWeights.Base, so an empty container still carries its share of the worker's floor. A worker holding no container contributes nothing; its load shows up in the mesh's mean only.
This is a proxy: a container full of static props costs less than one full of NPCs chasing paths. The hint's cost multiplier (phase 3) is the manual correction.
| Parameter | Description |
|---|---|
result | Cleared and filled with container id -> attributed utilization. |