Time Synchronizer

Read time 3 minutes Package: Nalix.Network
On this page

TimeSynchronizer is a high-precision, low-latency service that emits periodic “ticks” to synchronize state across the server. It is typically used for 60Hz heartbeat logic, physics-step synchronization, or periodic traffic flushing.

Source Mapping

  • src/Nalix.Runtime/Timekeeping/TimeSynchronizer.cs

Why This Type Exists

Maintaining a consistent “Server Time” cadence is critical for deterministic real-time systems. TimeSynchronizer provides:

  • Fixed Cadence: Built-in support for ~16ms (~60 FPS) ticks using high-precision timers.
  • Worker Isolation: Runs in a managed background worker to prevent application logic from drifting the server’s master clock.
  • Drift Detection: Automatically identifies and logs “Tick Overruns” if a handler blocks the synchronization line for too long.

Synchronization Pipeline

The following diagram shows the internal loop and how it dispatches time signals to registered handlers.

Architecture Diagram
flowchart TD
    subgraph Core[Master Sync Loop]
        Timer[PeriodicTimer - 16ms]
        Wait[Wait for Next Tick]
    end

    subgraph Dispatch[Dispatcher Logic]
        SyncCheck{FireAndForget?}
        SyncExec[Run Handler on Loop Thread]
        AsyncExec[Queue to ThreadPool]
    end

    subgraph Monitoring[Stability Monitor]
        Clock[Read Clock.UnixMillisecondsNow]
        Overrun{Elapsed > 1.5x Period?}
        Warn[Log Warning: Tick Overrun]
    end

    Timer --> Wait
    Wait --> Clock
    Clock --> SyncCheck
    
    SyncCheck -->|No| SyncExec
    SyncCheck -->|Yes| AsyncExec
    
    SyncExec --> Overrun
    AsyncExec --> Overrun
    
    Overrun -->|Yes| Warn
    Overrun -->|No| Timer

Internal Responsibilities (Source-Verified)

1. High-Precision Timing

The synchronizer utilizes the .NET PeriodicTimer, which is more efficient than Task.Delay for long-running loops. It defaults to a 16ms period (equivalent to 62.5 ticks per second), providing a smooth baseline for real-time networking.

2. Execution Modes (FireAndForget)

You can control how handlers are executed via the FireAndForget property:

  • FireAndForget = false (Default): Handlers run directly on the synchronization thread. This provides the lowest possible latency but risk “Tick Overruns” if the handler logic is heavy.
  • FireAndForget = true: Handlers are dispatched to the ThreadPool. This protects the sync loop’s precision but introduces a small dispatch delay.

3. Stability Monitoring

If a tick takes longer than 150% of the allocated period to complete, the synchronizer emits a warning: [NW.TimeSynchronizer] tick overrun elapsed=Xms period=Yms This is a critical diagnostic for identifying identifying bottlenecks in the real-time hot path.

Public APIs

  • event TimeSynchronized: The primary event raised every tick, providing the current Unix timestamp in milliseconds.
  • Period: Gets or sets the tick interval (Default 16ms). Setting this while running triggers an internal Restart().
  • Activate() / Deactivate(): Explicitly starts or stops the background synchronization loop.
  • FireAndForget: Toggle between synchronous and asynchronous handler execution.