Skip to content

Understanding ECS Debugging & Profiling

Why Debugging ECS is Different

Entity Component System architectures present unique debugging challenges compared to traditional object-oriented code. Instead of inspecting individual objects with encapsulated state, you're dealing with:

  • Entities: Just numeric IDs with no inherent meaning
  • Components: Data scattered across archetype tables
  • Systems: Functions that operate on query results, not objects
  • Deferred operations: Commands that execute later, not when called

This separation of data and logic makes traditional breakpoint debugging less intuitive. You can't simply "step into" an entity to see what it's doing.

The Stats Overlay Philosophy

The built-in stats overlay provides runtime observability rather than step-through debugging. It answers questions like:

  • "How many entities exist right now?"
  • "Which systems are slow?"
  • "Are my archetypes fragmenting?"
  • "Is my frame budget being exceeded?"

This approach aligns with how games and simulations are typically debugged—by observing the running system rather than pausing it.

What the Metrics Mean

Entity & Archetype Counts

The relationship between alive entities, archetypes, and rows tells you about your data layout:

Metric Healthy Sign Warning Sign
Archetypes Stable, low count Growing unboundedly
Rows ≈ Entities Close match Large gap indicates fragmentation
Entities Predictable growth Unexpected spikes

Archetype explosion occurs when entities frequently add/remove components, creating many unique component combinations. Each unique combination requires its own archetype table.

Frame Timing

The overlay tracks two time measurements:

  • dt: Delta time passed to update() (what your game logic sees)
  • frame: Actual wall-clock time spent in the update (what the CPU experiences)

When frame consistently exceeds dt, you're falling behind real-time.

Phase & System Timing

With the Schedule API, systems are grouped into phases. The overlay shows:

  • Per-phase total time
  • Per-system time (when profiling is enabled)

This helps identify which phase or system is the bottleneck.

Profiling History

The overlay maintains a rolling history (default: 120 frames) displayed as a bar graph:

  • Blue bars: Frames within budget (≤ slow threshold)
  • Red bars: Slow frames (> slow threshold)
  • White line: Target frame time

Patterns in this graph reveal:

  • Periodic spikes: Often garbage collection or physics sync
  • Gradual increase: Memory leak or unbounded growth
  • Consistent red: Fundamental performance problem

Debug Logging

The / toggle enables console output of phase timings each frame. This is useful for:

  • Capturing timing data for analysis
  • Correlating visual stutters with logged spikes
  • Automated performance regression testing