Performance Patterns
This page captures the runtime performance techniques used in Ghost.Entities and how to apply them.
Data Layout
- Archetype storage uses contiguous component arrays per chunk.
- Chunk memory is fixed-size (
Chunk.CHUNK_BUFFER_SIZE) to bound allocations and improve locality. - Component layouts are precomputed per archetype:
- offset,
- size,
- enable-bit offset,
- version index.
Why it matters:
- Sequential memory access in inner loops.
- Fewer pointer indirections than object-per-entity layouts.
Structural Cost Model
Structural changes are intentionally explicit and potentially expensive.
AddComponent/RemoveComponentmove entities between archetypes.- Removal uses swap-back compaction to keep chunks dense.
- Batch destroy path sorts locations and processes by chunk to reduce random work.
Guidance:
- Prefer bulk creation APIs (
CreateEntities) over repeated single inserts. - Minimize structural churn in hot update loops.
- Use
EntityCommandBufferto defer structural edits.
Query Efficiency
- Queries are compiled into bitset masks.
- Query instances are cached by mask hash in
ComponentManager. - New archetypes are incrementally tested and added to existing query match lists.
Guidance:
- Build query once, reuse query ID.
- Avoid rebuilding identical queries every frame.
Enableable Components
Enableable state is stored in bitmasks per chunk.
- Toggle with
EntityManager.SetEnabled<T>(...). - Query semantics (
WithAll,WithNone,WithDisabled,WithPresent) combine structural and enablement checks.
Guidance:
- Prefer enable/disable for state toggles over add/remove where possible.
Change Versioning
The runtime tracks:
- world version (
World.Version), - chunk structural version,
- per-component version per chunk.
ChunkView APIs such as HasChanged<T>(version) allow change-filtered work.
Guidance:
- Cache last processed version per system/subsystem.
- Skip unchanged chunks/components when possible.
Jobs and Parallel Chunk Processing
EntityQuery.ScheduleChunkParallel transforms matched chunks into job batches and schedules IJobParallelFor work.
Guidance:
- Use chunk jobs for broad data transforms.
- Keep
batchSizetuned for your workload. - Chain dependencies correctly and wait only at necessary sync points.
Allocation and Lifetime Hygiene
- Temporary data often uses stack/temporary allocators (
AllocationManager.CreateStackScope). - Persistent containers are explicitly disposed.
Guidance:
- Keep temporary allocations scoped and short-lived.
- Always dispose worlds, schedulers, and persistent collections deterministically.