Entity Component Systems Shootout: EntityX, Anax, Artemis (C++)

I tried out the three most popular Entity Component Systems (EntityX, Anax, Artemis-Cpp) and am now ready to report how they compare to each other. I will also share some benchmark results obtained simply by using Xcode unit tests and its measureBlock: method.

You’ll find the Entity Component Systems test project on github with EntityX, Anax and Artemis already integrated and working. If you need help installing these ECS libraries to your own project you’ll find my previous ECS article about installing ECS libraries helpful.

Let’s start comparing the APIs, then we’ll look at benchmark results.

Creating the World

The “world” object is the container for all entities. Note that I decided to create these objects with new solely because of compile errors. You can of course create the worlds on the stack as well and use dot notation instead.

Artemis already provides a glimpse at its more verbose nature.

Creating Entities with Components

At the core of an ECS you’ll work with entities and their components. This code will create an entity, add components to it, register it with the world and finally delete it.

EntityX is clearly the easiest and least error-prone to work with. It does not require “activating” or “refreshing” the entity in order to register it with the world and to register its components with the component systems.

Anax requires you to activate the entity after creating it. Don’t forget to do so or the entity’s components will not be processed by the component systems. Furthermore you also have to refresh the world whenever the active status of an entity has changed, although you can bulk the creation of multiple entities and then only refresh the world once per frame.

It sure would have been nice if Anax would just do that automatically. Because there’s one big problem with that: if you refresh the world without any entity changing its active state, Anax effectively stops processing all entities!

Artemis requires you to refresh the entity after creating it, but it also has you create instances of the component classes on the heap with the new keyword.

Interestingly, EntityX prefers to destroy entities, Anax likes to “kill” them (even though they aren’t necessarily “living” things) and Artemis is quite technically correct and just removes entities from the world.

Creating Components

Let’s take a closer look at the components and how they are designed.

Again, EntityX shows off its simplicity. Components merely need to be structs – that’s all! Though Anax merely wants you to subclass the struct from anax::Component so there’s not much give or take here.

Artemis requires you to use subclasses of artemis::Component for its components. Constructor and members ought to be public hence the public: specifier must be added.

Overall in all three ECS the creation of components is simplistic. After all, they merely represent chunks of data with EntityX taking that point to the absolute minimum.

Creating Component Systems

Component systems implement game logic by using the entities components. Such systems need to require a specific set of components to work with (dependencies), they need to obtain a list of (active) entities with such components, and they need to call a processing function that typically runs every frame.

Again you can see the verbosity increasing from EntityX over Anax to Artemis. Both EntityX and Anax continue to prefer structs.

EntityX uses an update method with three parameters where entityx::EntityManager is identical to the world->entities member. The event manager is exclusive to EntityX as it’s the only ECS with a built-in event system that allows events to be passed on to registered receivers – a way to allow components to communicate with other, unrelated components.

EntityX then uses

to specify the dependent components. This means the provided lambda function runs for every active entity that has both Position_EntityX and Direction_EntityX components. The lambda takes an entity as parameter plus one parameter for each dependent component.

Anax in contrast requires you to specify dependencies at the top of the system:

It then simply calls the system’s update method that just takes a delta time parameter.

Meaning you have to get the list of entities and enumerate over it yourself, plus getting each entity’s components during enumeration. Anax is more verbose but also more flexible, and that flexibility might allow for multithreading component system updates. Neither EntityX nor Artemis can offer that, as they already pass in a reference to an entity in the system’s update method.

Artemis’ component systems feel bloated in comparison, yet they’re still reasonably short for a class. You have to register the system’s dependencies in the constructor:

You will also need instances of artemis::ComponentMapper for each component, I presume this is Artemis’ way of filtering entities based on their components. The processEntity method is called for each entity and the mappers provide the entity’s components. Also the delta time – if you need it – needs to be obtained from the world.

Overall you won’t have that many systems in a project so the verbosity should not really be an issues, with most of the code going into the processing (update) functions anyway.

Registering Component Systems

Let’s compare how the component systems are registered with the world object.

Here each ECS has its own style. EntityX wants you to add the type and then configure the systems which calls the system’s function of the same name. This allows each system to perform post-init tasks such as registering itself as an event listener.

Anax merely wants you to pass in a reference to a system. This will automatically call the system’s initialize function.

Artemis is slightly different as it has a dedicated SystemManager to which you “set” new instances of the system classes. The initializeAll method will then call each system’s initialize function.

Overall EntityX has a slight advantage when it comes to simplicity of the API with Artemis taking the back row as it feels more like “classic” C++.

Updating Component Systems

Typically every frame you’ll want to update the systems, which then runs their processing (update) function.

In EntityX you simply call update_all and done. However this means the order of component system updates depends on the order they were added to the world, and it makes it more difficult to temporarily disable systems.

Anax allows you to manually change the execution order of systems by manually calling them. This allows you to easily skip certain systems based on game state (ie game paused, player died).

Artemis once again has you jump through more hoops than needed, though overall the lack of brevity is still negligible.

Benchmark Results

Curious to see how these ECS compare against each other in terms of performance? I know I was. And I was somewhat surprised by the results.

All Equal: Creating & Removing Entities

One thing ahead of time: creating and removing entities as well as assigning components to them takes almost the same time for each ECS. Artemis takes marginally more time for this, but it almost seems like this is a tradeoff for its fast component system update performance.

In any case, creating and destroying entities isn’t a performance critical aspect, as you’ll be doing that relatively rarely at runtime, while updating the component systems is a task performed for most entities every frame. So I decided to focus on that aspect.

In any case, if you do need to create and throw away a lot of entities per frame, you should consider simply deactivating and pooling deactivated entities to minimize the create/destroy overhead. It seems Anax with its builtin entity activation system and entity caches may perform rather well in that area.

Test Setup

For each number of entities I ran the measuring unit test target several times. I stopped running the tests when subsequent runs stopped producing faster results. The results below are the fastest ones I could get, to rule out any OS interference as much as possible.

Of course I used the release configuration with default compiler optimizations but with GCC_FAST_MATH (Relax IEEE Compliance build setting) enabled. Tests were run on OS X 10.11. The time scale (Y) is in thousands of milliseconds (18 = 18,000 milliseconds).

Each test simulates a loop of 1,000 component system updates (aka 1,000 frame updates). If you want the milliseconds for a single frame, divide the results by 1,000. For instance if processing 400 entities takes 2,000 milliseconds then that’s about 2 milliseconds per frame and would account for 1/8th of the 16.666 milliseconds you have per frame for a 60 fps game.

Test Code

This is the code that was profiled for each entity system. Only the code in the MEASURE macro is profiled, the rest is just setup code. Basically all entities contain 2-3 components and there are two systems, all performing the exact same task. The systems don’t do much other than adding/multiplying numbers and assigning them.

Results

I started with 25 entities and kept doubling that number until 3200 entities, to get a feel for how well the systems scale respectively what their overhead in “sparsely populated worlds” might be.

Entity Component System Benchmark Results
Entity Component System Benchmark Results: EntityX doesn’t scale well

One thing becomes apparent: EntityX doesn’t scale well. Its sweet spot is just about 100 entities, from then on it keeps taking ever longer compared to the others.

You can see by the trendlines that both Anax and Artemis scale almost identically, with Artemis maintaining a small but almost constant lead.

Recommendations

EntityX (459 Stars, 85 Watches, 85 Forks) provides the least verbose API and the most functionality. It’s relatively easy to use, it’s built-in event system is a welcome solution to a common component-system problem. I would definitely recommend it to beginners.

However, if you plan on having significantly more than 200-400 entities in the same world you may be better off looking into the other ECS libraries as the performance penalty may become a limiting factor.


Anax (172 Stars, 23 Watches, 16 Forks) is still comparatively easy to use and it’s only marginally more verbose than EntityX. Personally I consider it’s component system API to be the best of them all. If you want the most flexibility and don’t want to compromise on speed (much), Anax will be your best choice.

The downside is that Anax requires you to properly activate new entities and then refresh the world. This extra housekeeping work can be tedious and result in annoying bugs if not done with discipline or some wrapper functions.


Artemis-Cpp (143 Stars, 40 Watches, 59 Forks) is the best choice if utmost performance is of utmost priority, especially if you expect to have several hundreds if not thousands of entities. Artemis is also the only library not using C++11 so it’ll work fine with older compilers and is more likely to be compatible with fringe platforms and their compilers.

I still wouldn’t recommend Artemis though, mainly because there seems to be no project ownership and no updates nor support. Artemis code will also be far more verbose than that of EntityX and Anax. And Anax is still really fast – whether 3,000 entities take 5 or 6 milliseconds to process per frame is almost negligible.

More Things to Consider

  • EntityX has a built-in event system for infrequent exchange of data between component systems. For instance this can be used to decouple audio playback from the systems into its own audio system, or to pass on collision information from the collision system to, for instance, the “projectile” and “entity health” systems. Again: beginner-friendly and simply convenient. However using the event system will take an additional toll on performance.
  • EntityX and Anax support and use C++11. Artemis does not use C++11 features but (of course) compiles fine as C++11 code.
  • EntityX and Anax github repositories are fairly active (commit-wise), with both authors being fairly responsive too. Though for Anax there are curiously few community contributions (just 3 contributors) while EntityX has integrated pull requests from over a dozen contributors. This may be a result of EntityX popularity and being the older project (about 6 months).
  • Artemis’ github repository hasn’t been updated in 2 years, with last responses from library contributors dating back 1.5 years. This makes the project unmaintained and any issues arising from it are likely your own to solve.
  • Multi-threading is certainly not supported out of the box by any ECS. You can’t implement multithreaded component system updates in EntityX and Artemis without heavily modifying the project, as their systems pass a single entity to the system’s update method. The jury is still out there regarding anax, but given that its component system’s update method requires you to iterate over the entities yourself, it seems reasonable to assume that a system could update its entities concurrently. At least as long as you only modify component members.

Comments

Loading Facebook Comments ...

Leave a Reply

Your email address will not be published. Required fields are marked *