Releases: ark-ecs/Ark.jl
v0.4.0
Ark v0.4.0
Ark.jl v0.4 focuses on bringing parallelization to the core of the system. This major release introduces three powerful new features: seamless integration with all major GPU backends for component storage, the ability to use custom user-defined storages, and support for parallel queries.
Release highlights
GPU Storage
Here, it is possible to appreciate how in the new nbody demo the performance on a NVIDIA GeForce GTX 1650 is almost 20 times better than using all the 6 cores of my AMD Ryzen 5 5600H CPU:
| Video 1 | Video 2 |
|---|---|
cpu.mp4 |
gpu.mp4 |
This is made possible by the new GPUVector and GPUStructArray component storages. These utilize unified memory to allow for efficient mixed CPU and GPU operations, and are fully compatible with many major backends like CUDA.jl, Metal.jl, oneAPI.jl, and OpenCL.jl.
Custom Storages
Ark.jl now allows to easily plug any data structures into the ECS which implements the storage interface. As long as the new storage is a one-indexed subtype of AbstractVector and implements the interface, it can be used. For example, this flexibility allowed us to easily integrate UniqueVectors.jl to support components optimized for O(1) searches.
Parallel Queries
Queries in archetype‑based ECS are already highly efficient, but this release introduces the necessary tooling to support parallel queries for even greater performance. With this, one can run multiple queries simultaneously thanks to a thread-safe locking mechanism.
Benchmarks with Agents.jl
We also compared Ark.jl with Agents.jl by faithfully reimplementing the benchmarks at https://github.com/JuliaDynamics/ABMFrameworksComparison. The results show that Ark.jl is 2-7x faster than Agents.jl on those! A result which surprised me a bit, since the way those benchmarks are structured don't really allow for an ECS to shine too much. We lose instead pretty much in the LOCS category since currently no spatial facility is implemented for Ark.jl which was then needed to be recreated inline to run these benchmarks.
Changelog
Breaking changes
- Storage modes wrap the storage types instead of using unrelated types (#437)
Features
- Adds support for user-defined storage types (#437)
- Adds new types
GPUVectorandGPUStructArraywhich can be used to offload work to the GPU (#470, #476, #483) - Makes the locking mechanism thread-safe for parallel queries (#536, #537)
- Adds support for shuffling tables based on filters (#527)
- Adds support for UniqueVector storage (#481)
Performance
Bugfixes
Documentation
- Adds a demo of a nbody model to show GPU computing (#523)
Other
- Closing an already closed query is a no-op instead of raising an error (#493)
Merged pull requests:
- Do not throw on close! for fully iterated queries (#493) (@ameligrana)
- Update CHANGELOG for v0.3.2 release (#513) (@mlange-42)
- Improve _shallow_copy implementation (#515) (@ameligrana)
- Improve redirection to faster copy versions (#517) (@ameligrana)
- Use getfield in struct array methods (#519) (@ameligrana)
- Add unchecked keyword (#522) (@ameligrana)
- A Nbody demo as a GPU-first example (#523) (@ameligrana)
- Update Mooncake version to include 0.5 (#524) (@ameligrana)
- Implement shuffle of tables (#527) (@ameligrana)
- Add check for locked world in shuffle_entities! (#528) (@ameligrana)
- Add unchecked benchmark for world_get_5 function (#530) (@ameligrana)
- Create unchecked macro (#531) (@ameligrana)
- Add storage types to Query struct and related functions (#532) (@ameligrana)
- Implement copy specialization for StructArray (#533) (@ameligrana)
- Add _check_locked calls earlier (#535) (@ameligrana)
- Simplify locking mechanism (#536) (@ameligrana)
- Make lock thread-safe (#537) (@ameligrana)
- Use masks in has_components (#538) (@ameligrana)
- Add benchmark for has_components (#539) (@ameligrana)
- Add another has_components benchmark (#540) (@ameligrana)
- Update setindex! to return the new value instead of nothing (#541) (@ameligrana)
- Update ReadMe for 0.4 (#542) (@ameligrana)
- Change IteratorSize for Query type to HasLength (#543) (@ameligrana)
- Revert "Update ReadMe for 0.4" (#544) (@ameligrana)
- Update ReadMe for 0.4 release (#545) (@ameligrana)
- Prepare release 0.4 (#546) (@ameligrana)
- Fix link in ReadMe (#548) (@ameligrana)
- Update changelog for version 0.4.0 release (#549) (@ameligrana)
Closed issues:
Ark.jl v0.3.2
Ark.jl v0.3.1
Ark.jl v0.3.0
Ark.jl v0.3.0
Ark.jl v0.3 is our biggest feature release yet. It introduces first‑class entity relationships, expands batch operations far beyond entity creation, and delivers substantial performance improvements.
Release highlights
Entity relationships
This release adds first‑class support for entity relationships, allowing you to express connections between entities directly using ECS primitives. While it is possible to express relations by storing entities inside components, the tight integration into the ECS provides several benefits. Most importantly, relationship can be queried now as efficiently as component queries. In addition, relationships become more ergonomic, more consistent, and safer to use.
For details, see the user manual's chapter on Entity relationships.
Batch operations
Previous versions of Ark.jl already offered blazing‑fast batch entity creation. This release generalizes the concept to all operations that modify entities or their components. You can now remove all entities matching a filter, add components to all matching entities, and more, using a single batched call. These operations are typically at least an order of magnitude faster than performing the same changes individually.
For details, see the user manual's chapter on Batch operations
Cached queries
Queries in archetype‑based ECS are already highly efficient, but this release introduces cached queries for even greater performance, especially in worlds with many archetypes. Instead of checking the components of all archetypes in the pre-selection (which is based on the most "rare" component in a query), cached queries maintain a list of all matching archetypes. This means matching checks are only needed when a new archetype is created, eliminating overhead during query iteration.
Performance improvements
Numerous optimizations to component operations and the archetype graph yield significant speedups. Component operations are now 1.5–2× faster, and entity creation is up to 3× faster than before.
Changelog
Breaking changes
- Batch entity creation uses a callback/
do-block instead of an iterator (#400)
Features
- Adds entity relationships (#340, #349)
- Adds events for relationship changes (#370)
- Adds re-usable filters for query construction (#375, #413)
- Adds cached/registered filters for faster query iteration with many archetypes (#378)
- Adds batch entity removal (#396, #402)
- Adds batch-setting entity relation targets (#406)
- Adds batched versions of adding, removing and exchanging components (#408)
- Makes Ark compatible with Mooncake.jl (#405)
Performance
- Uses a hash table for some component transitions, with up t0 30% speedup (#348)
- Uses
push!instead ofresize!+setindex!for moving and creating components (#439) - Caches the last component transition, with 15-35% speedup (#448)
Documentation
Bugfixes
Other
- Ark.jl moved from the personal account of its initiator to the ark-ecs organization
Ark.jl v0.2.0
Ark.jl v0.2.0
Two weeks and roughly 100 PRs after the last release, we are pleased to announce Ark.jl v0.2.0!
This release comes with several new features, extended documentation and some performance improvements, but also with a few breaking changes.
Release highlights
Event system
The highlight of this release is Ark's new comprehensive event system built around lightweight, composable observers. Observers allow applications to react to ECS lifecycle changes, such as entity creation, component addition or removal, and relation updates. Observers can defines filters to match relevant events as well as entities. They follow the same declarative patterns as Ark’s query system.
Beyond built-in lifecycle events like OnCreateEntity and OnAddComponents, the system supports custom event types. Custom events can be emitted manually and observed using the same filtering and callback mechanisms, making them ideal for modeling domain-specific interactions such as input handling, and other reactive game logic.
Configurable component storages
The backing storages for components can now be configured on a per-component basis. Available storages are ordinary Vectors as well as a StructArray-like data structure. StructArray-like storages have the advantage that they allow for boradcast operations on component fields instead of iteration over entities.
For a consistent and convenient API, StructArray-like field access is also possible for Vector storages, thanks to the new FieldViews.jl package.
Other features
Further new features available in v0.2.0:
reset!the World for more efficient repetitions of simulations.initial_capacityin the World constructor to avoid repeated allocations.copy_entity!for easier construction of similar entities.lengthandcount_entitiesfor queries and batches.
API improvements
The macro versions of some functions that allowed for more convenient componen type tuples were removed. Functions now support the convenient syntax directly.
Documentation
Of course, all new features were thorougly documented. But on top of that, we now also provide a number of demos that demonstrate Ark's features and serve as stand-alone, runnable examples.
Changelog
Breaking changes
- Removes the macros for the convenient tuple syntax, the syntax is used in ordinary functions now (#305)
- Throws more explicit exception types instead of generic
ErrorException(#202) - Query argument
optionaladds further components instead of making existing ones optional (#253)
Features
- Adds an event system with events for structural changes as well as custom events (#155)
- Adds storage modes Vector and StructArray, which can be selected per component type (#207, #225)
- Adds field view, so field access for query columns works equally for Vector and StructArray storages (#213)
- Adds support to manage an arbitrary number of components in the
World(#230, #327, #330) - Adds
@copy_entity!for copying an entity and optionally adding and removing components (#262, #266) - Adds keyword argument
initial_capacityto World constructor (#288) - Adds function
reset!for resetting and reusing a world to avoid reallocations (#292) - Adds function
lengthfor queries and batches (#298) - Adds function
count_entitiesfor queries and batches (#316)
Performance
- Adaptive bit-mask size, depending on the number of components in the world (#237, #250)
- Avoids unions in queries without optional components, speeding up query iteration (#246)
Documentation
- Adds an animated logo demo (#268)
- Adds a basic SIR demo (#324)
- Adds a demo of an evolutionary model for grazers (#325)
- Adds a demo with travelers on a network (#334)
- Adds a boids/flocking demo (#337)
- Adds a page listing all demos with screenshots in the user manual (#339)
Other
Ark.jl v0.1.1
Bugfixes
- Fix broken archetype pre-selection in queries (#301)