Ark ECS
repository·main·Indexed 43 days ago
https://github.com/mlange-42/arkA high-performance, archetype-based Entity Component System (ECS) for Go. It features a type-safe API, zero dependencies, and a query-based architecture designed for game engines and simulations. Key capabilities include entity relationships, an extensible event system, and world serialization via the ark-serde package.
What's inside Ark
- Ark is an archetype-based Entity Component System (ECS) for Go. It is designed for high performance and provides a type-safe API for managing entities and components. Unlike many ECS frameworks, Ark does not enforce a 'systems' architecture; instead, it focuses on providing powerful queries, allowing developers to use their own structures or provided tools to drive logic.
Understand Ark's core API and design philosophy
mainArk is an Entity Component System (ECS) designed primarily for scientific, individual-based models, though it is also suitable for game development. Its core is the
Worldobject, which acts as a data store for entities and components.Key design principles include:
- Simplicity & Type-Safety: Uses Go generics to provide a fully type-safe API for queries and component manipulation. This ensures compile-time safety and avoids the performance overhead of reflection.
- Performance: Uses archetype-based storage for cache-friendly memory layouts and supports batch operations.
- Determinism: Guarantees that identical operations on the same
Worldwill always produce the same iteration sequence, ensuring reproducible simulations. - Safety: Ark prioritizes strict behavior over silent failures. It will panic on violations such as removing a dead entity, adding a duplicate component, or attempting to modify a locked world.
- Minimalism: Ark does not include a built-in update loop or systems; these are implemented by the user to provide maximum control.
Ark Key Features
mainArk provides several core capabilities for building game engines or simulations in Go:
- Performance: Highly optimized archetype-based architecture (see Benchmarks for details).
- Type-Safe API: Well-documented and type-safe interfaces.
- Entity Relationships: Supported as a first-class feature.
- Extensible Event System: Includes filtering and support for custom event types.
- Batch Operations: Fast operations for mass manipulation of entities.
- Query-Centric: No mandatory 'systems' requirement; logic is driven via queries.
- Serialization: Supports world serialization and deserialization via the
ark-serdepackage. - Zero Dependencies: The core library has no external dependencies.
Explore Ark example patterns
mainThe
examplesdirectory contains several implementations demonstrating core Ark features and integration patterns:- Minimal Setup:
readmeprovides the simplest possible usage pattern. - Entity Relationships:
relationsshows how to manage connections between entities. - Event Systems:
eventsandcustom_eventsdemonstrate built-in and user-defined event types. - Concurrency & Locking:
world_lockshows how to manipulate entities while the world is locked during query iteration;parallel_queriesdemonstrates parallel query execution;parallel_runsshows how to run multiple simulations in parallel. - Systems & Scheduling:
systemsdemonstrates implementing systems and a scheduler. - Hybrid Data Structures:
entity_gridandkdtreeshow how to mix ECS with non-ECS structures like grids or k-d trees. - Engine Integration:
ebitenginedemonstrates using Ark with the Ebiten game engine.
- Minimal Setup:
Understand the Array of Structs (AoS) benchmarks
mainThebenchmark/aosdirectory contains the source code used to generate the performance comparison plots between Ark's data layout and the standard Array of Structs (AoS) pattern. These benchmarks are specifically used to illustrate the performance characteristics discussed in the Filters & queries section of the user guide.Explore external tools for Ark
mainArk has a growing ecosystem of external tools designed to extend its functionality. Key tools include:
- ark-serde: Handles JSON serialization and deserialization for Ark's
World. - ark-tools: Provides essential ECS components like systems and a scheduler.
- ark-pixel: Integrates OpenGL graphics and live plotting using the Pixel game engine.
- ark-serde: Handles JSON serialization and deserialization for Ark's
Available Ark ecosystem tools
mainArk provides several companion tools for extended functionality:
- ark-serde: Provides JSON serialization and deserialization for an Ark
World. - ark-tools: Provides systems, a scheduler, and other utility structures for Ark.
- ark-pixel: Provides OpenGL graphics and live plots via the Pixel game engine.
- ark-serde: Provides JSON serialization and deserialization for an Ark
Performance trade-offs of archetype-based ECS
mainWhile archetypes optimize for fast iteration, they introduce costs when modifying an entity's composition.
The Cost of Mutation
- Component Changes: Adding or removing a component requires relocating the entity to a different archetype. This involves moving all existing component data for that entity, costing approximately 20ns per involved component.
Optimization Strategies
- Batch Mutations: To minimize relocation costs, add, remove, or exchange multiple components simultaneously rather than performing individual operations sequentially.
- Batch Commands: Use batching to manipulate many entities in a single command to improve efficiency.
Use component mappers to manage entity components
mainArk provides component mappers (such as
Map1,Map2, etc.) as helpers to create entities with specific components, add components to existing entities, or remove components from them.Because of Go's generic limitations, mappers are parameterized by the number of components they handle (e.g.,
NewMap2handles two components). For managing a single component type, use the dedicatedMapmapper, which provides additional specialized methods.// Example usage of a mapper (conceptual based on documentation) // NewMap2 denotes a mapper for 2 components mapper := ecs.NewMap2[ComponentA, ComponentB]() entity := mapper.Create(world, compA, compB) // ... mapper.Add(world, entity, compA) mapper.Remove(world, entity, compB)When to use entity relations vs. standard components
mainChoosing between Ark's first-class relations and manual component storage (e.g., storing a slice of entities in a struct) depends on your data distribution:
Use Entity Relations when:
- You have a moderate number of relation targets.
- There are many entities per target (e.g., many animals in one farm).
- You want to use efficient queries to find all entities related to a specific target.
- You need to represent abstract categories (e.g., factions, render layers, or FSM states) as entities.
Use Standard Components (e.g.,
[]ecs.Entity) when:- You have a very high number of target entities (tens of thousands).
- You have 1:1 relationships (storing the target entity directly in a component is more efficient).
How the archetype graph accelerates component changes
mainArk uses a dynamic archetype graph to quickly find the new archetype when components are added or removed.
Graph Mechanics
- Nodes and Transitions: Nodes represent archetypes. Arrows (transitions) represent adding (solid head) or removing (empty head) a single component.
- Search Algorithm: When an entity's composition changes, the system follows existing transitions in the graph. If a transition doesn't exist, it searches through nodes using the component mask and creates new nodes/connections on demand.
- Performance: Transitions are stored within nodes using a lookup mechanism that is approximately 10x faster than a standard Go
map. The graph typically stabilizes quickly during a simulation run.
Archetype and table recycling for relations
mainArk manages memory for relation-based archetypes through specialized recycling:
- Relation Tables: Unlike standard archetype tables, sub-tables created for relation targets can be recycled.
- Recycling Process: When a target entity dies, its associated sub-table is deactivated. The memory for entities and components is retained.
- Reuse: If a new request is made for a table in the same archetype for a different target entity, Ark reuses a recycled table if one is available.
- Tracking: Ark uses a bitset to efficiently track which entities are currently targets of a relation to determine if a table can be safely removed.