Core · class
StepBudget
Explained in The loop.
class StepBudget<Label = string>import { StepBudget } from '@driftengine/core';Constructor
new
constructor(options?: StepBudgetOptions)| Parameter | Type | Description |
|---|---|---|
options? | StepBudgetOptions |
Accessors
| Name | Type | Description |
|---|---|---|
estimateget | number | What one more stop is currently assumed to cost. Decays; see StepBudgetOptions.forget. |
worstget | number | The longest single stop ever taken. Does not decay: this is the report, not the guard. |
worstInget | Label | null | The label the caller gave the longest stop.MoreA budget being blown is useless information without the name of the unit that blew it.
That is the whole reason |
Methods
spend
spend(budgetMs: number, next: () => Label | null): numberAdvance the caller's work for up to budgetMs, and say how many stops that took.
| Parameter | Type | Description |
|---|---|---|
budgetMs | number | |
next | () => Label | null |
More
next performs exactly one indivisible unit and returns a label naming what it did, or
null when there is nothing left to do — which ends the call without counting a stop.
Return the label of the work just done, not of the work about to be done. The two are easy to confuse where a job names its own next phase, and the report that results sends a reader to the wrong builder every time the phase changes.
The two rules the loop is made of, both arrived at by getting them wrong first:
- Do not start what you cannot finish. A driver that keeps going while any budget remains overshoots by a whole stop. Measured by a consumer at 30 Hz: 8.3 ms of budget plus an 8.6 ms stop against a frame of 16.7.
- But always do one. Without the unconditional first stop, a unit costing more than the whole budget means nothing ever advances at all, and a world that never loads is worse than a frame that runs long.