Execution Modes
Today: a fixed-timestep tick loop (plus a single-threaded debug variant); event-driven and hybrid request/response modes are designed but not yet built.
Status: π§ Partial Β· Visibility: Public Β· Level: π£ Advanced Β· Category: Tick-Based Execution Engine
π― What it solves
Game servers split into two broad dispatch shapes: continuous simulation (FPS/MMO/survival β work
happens every tick whether or not a player acts) and discrete request/response (turn-based/card/idle
games β work happens only when a player acts). Forcing one shape onto the other either pays a full
tick's overhead for an idle turn-based game, or bolts a fake tick loop onto something that's
naturally event-driven. TyphonRuntime is designed to host either shape; today only the tick-driven
shape is implemented.
βοΈ How it works (in brief)
TyphonRuntime.Create + Start() runs a fixed-timestep loop: a dedicated Typhon.TickDriver thread
fires ticks at RuntimeOptions.BaseTickRate Hz, and every tick executes the full registered system
DAG through the runtime-owned UoW/Transaction lifecycle (see
Tick Lifecycle & Transaction Management). Setting
RuntimeOptions.WorkerCount = 1 collapses the worker pool onto the TickDriver thread itself, running
every system synchronously in topological order β the same ShouldRun/Prepare/skip/failure
machinery as multi-threaded execution, just on one thread. This is a genuine single-threaded
execution path (not a simulated one), useful for deterministic step-by-step debugging without
touching any other code.
π» Usage
using var runtime = TyphonRuntime.Create(engine, schedule =>
{
schedule.PublicTrack.DeclareDag("Game")
.CallbackSystem("Movement", ctx => { /* ... */ })
.CallbackSystem("AI", ctx => { /* ... */ }, after: "Movement");
}, new RuntimeOptions
{
BaseTickRate = 60, // Hz β the only execution mode implemented today
});
runtime.Start(); // spins up the worker pool + the Typhon.TickDriver metronome thread
// ... ticks fire on the metronome until Shutdown() ...
runtime.Shutdown();
runtime.Dispose();
// Single-threaded debug mode β identical schedule, deterministic in-order execution on one thread
using var debugRuntime = TyphonRuntime.Create(engine, configureSchedule,
new RuntimeOptions { BaseTickRate = 60, WorkerCount = 1 });
| Option | Default | Effect |
|---|---|---|
RuntimeOptions.BaseTickRate |
60 | Metronome rate (Hz) for the tick-driven loop |
RuntimeOptions.WorkerCount |
-1 (Max(1, ProcessorCount - 4)) |
Set to 1 for single-threaded, in-order debug execution |
β οΈ Guarantees & limits
- Only tick-based mode is implemented.
claude/design/Runtime/04-threading-and-modes.mdalso designs an event-driven mode (ProcessActionper player action, no tick loop, per-player serialized/cross-player concurrent dispatch) and a hybrid mode (tick loop + in-tick action dispatch), but there is noExecutionModeenum,ProcessAction, orRegisterActionHandlerin the current codebase β everyTyphonRuntimeruns the fixed-timestep tick loop. - Request/response workloads (turn-based, card, idle games) must currently be modeled as work
processed inside a tick (e.g. drain a queued-actions buffer from a
CallbackSystem) rather than through a dedicated event-driven dispatch path. - The tick rate is fixed at
BaseTickRatefor the runtime's lifetime; only the internal multiplier the overload detector applies under load (1Γ-6Γ) changes effective cadence β see Worker Pool & Threading Model. WorkerCount = 1still runs the full DAG (all phases, all tracks) β it changes where systems run (one thread, in topological order), not what runs.
π§ͺ Tests
- TyphonRuntimeTests β
SingleThreadedMode_TransactionWorksprovesWorkerCount = 1still gives systems a valid Transaction - DagSchedulerTests β
SingleThreadedMode_Works,SingleThreadedMode_PipelineSystem_AllChunksProcessedβ deterministic in-order execution of the same DAG
π Related
- Parent feature: Tick-Based Execution Engine
- Sibling: Worker Pool & Threading Model