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.

How to install Entity Component Systems: Anax, EntityX, Artemis (C++)

I’m currently testing three Entity Component System (ECS) libraries for inclusion in TilemapKit: Anax, EntityX, Artemis (C++).

I thought I’ll write down the installation steps for you. Since two of them rely on CMAKE for building they won’t work out of the box when dropped into an Xcode project.

The steps outlined here are tested with a new SpriteKit project created with Xcode 7.1 and compile for OS X. I assume iOS will be the same.

Working knowledge of Xcode and github is assumed. Also remember: if you use Objective-C and C++ together in the same project you’ll have to rename the .m files to .mm to compile the code as Objective-C++.

Adding Anax to an Xcode project

Anax uses CMAKE as build system. Therefore if you want to use it in a “regular” project that doesn’t use CMAKE the library requires a couple code changes, mainly replacing the CMAKE variables with actual values and fixing a compiler warning. It is still fairly easy to set up, should take less than 15 minutes.

  • Clone the repository
  • Rename include/anax/Config.hpp.inl to Config.hpp
  • Add all files in folders include and src to the desired target
  • Edit Config.hpp:
    • Replace all occurances of #cmakedefine with #define
    • Replace all CMAKE @identifier@ variables with actual values (see CMakeLists.txt for current values).
    • The affected lines and their values are:
  • Optional: edit EntityIdPool.cpp (line ~74). In function ::get change the return line to this one (cast added to suppress compiler warning):
  • Edit target’s Build Settings:
    • Locate the Header Search Paths setting
    • Add an entry pointing to anax’ include folder, for instance: $(SRCROOT)/anax/include
  • Import the main header in a source file:
    • #import "anax.hpp"
  • Done! Anax should compile without warnings using Xcode’s default build settings.

Adding EntityX to an Xcode project

EntityX also uses CMAKE and requires a few minor code changes as well. You should also ensure to not add or to remove all files with the _test suffix – unfortunately these unit tests are in the same folders as the rest of the source files. Nevertheless EntityX is easy to set up in less than 15 minutes.

  • Clone the repository
  • Rename entity/config.h.in to config.h
  • Add the folder entityx/entityx to the desired target
    • Note: that’s the folder containing config.h
    • Caution: do not add or subsequently remove all files with _test.cc suffix. You do not need to include the unit tests. Including them will cause linker errors (duplicate symbols).
      • It’s these files you should remove/avoid: Benchmarks_test.cc, Dependencies_test.cc, Entity_test.cc, Event_test.cc, Pool_test.cc, System_test.cc, TagsComponent_test.cc
  • Edit Config.h:
    • Replace all CMAKE @identifier@ variables with actual values (see CMakeLists.txt for current values).
    • The affected lines and their values are:
  • Edit target’s Build Settings:
    • Locate the Header Search Paths setting
    • Add an entry pointing to EntityX’ root folder (where README.md is), for instance: $(SRCROOT)/entityx
      • Caution: do not point the header search path to the entityx/entityx folder but the folder above that!
  • Import the main header in a source file:
    • #import "entityx.hpp"
  • Done! EntityX should compile without warnings using Xcode’s default build settings.

Adding Artemis-Cpp to an Xcode project

Artemis-Cpp is the easiest ECS to install as it does not rely on CMAKE. It only requires an (optional) code fix to avoid an ominous warning that occurs only in Xcode 7. Artemis should be ready to work with in under 10 minutes.

  • Clone the repository
  • Add all files in folders include and src to the desired target
    • Optional: you may want to remove the file Entity (no extension), it’s empty and doesn’t seem to serve any purpose.
  • Optional: edit SystemManager.cpp (line ~30):
    • Adding a cast to (void) fixes the warning: Expression with side effects will be evaluated despite being used as an operand to ‘typeid’
  • Edit target’s Build Settings:
    • Locate the Header Search Paths setting
    • Add an entry pointing to Artemis’ include folder, for instance: $(SRCROOT)/Artemis-Cpp/include
  • Import the main header in a source file:
    • #import "Artemis.h"
  • Done! Artemis-Cpp should compile without warnings using Xcode’s default build settings.

Which one should I go with?

I can’t say that yet – I’m still evaluating and benchmarking. I’ll post a summary of what I like/dislike about each ECS and which one I’ll be going with for TilemapKit by tomorrow. Stay tuned!

TilemapKit: what’s next?

The TilemapKit port to C++/Cocos2d-x is mostly complete, with only some fringe features missing. I’m confident that by early November TilemapKit v1.0 will be released. Then what?

First things first

I’m currently porting the Objective-C (SpriteKit, Cocos2D-SpriteBuilder) model classes to use the C++ model classes instead. This should be a transparent change, besides having to add another linker flag (-lc++) and adding a couple more source files.

Even though the model code includes C++ code users will not have to change file extensions from .m to .mm and all the issues associated with that.

Next Stop: ECS

I will add an Entity Component System to TilemapKit.

Not the one in GameplayKit, mind you. It’s been criticised for not being a “true” ECS as it follows the classic Scott Bilas’ ECS model where each entity updates its components in the order they appear in the entity’s components list.

However the Adam Martin ECS is far more popular among professional game developers. Here, a component system updates all components of the same type in sequence. Entities aren’t “updated” per se, they are merely containers (or database rows) for components which in turn only contain data. The core logic that works on this data is implemented by the component system.

Here’s a comparison of ECS models as pseudo-code.

Although you can implement a Martin ECS with GameplayKit, for TilemapKit I need one that’s cross-platform and preferably in C++. The candidates are entityXanax and Artemis. Since entityX seems more popular than anax you may be interested what the differences are in anax’ ECS.

Personally I’m leaning towards anax since it seems to get more love (commits, issues) than entityX, while Artemis’ C++ port hasn’t been updated in 2 years and purposefully doesn’t use C++11. Regardless of which one I’ll choose I will add an ObjC interface.

Oh an if you have a personal preference please leave a comment and explain why you like (or prefer) one ECS library (or design) over another.

Then: An ECS Example Game

Next, I will implement an example game using TilemapKit and the ECS in such a way that there’s only very little engine-specific code. Everything about the game world comes from TilemapKit with dynamic processing performed by the ECS and only at the very end of a frame update the entity transform component is applied to a visual node.

Of course you’ll be able to place objects in Tiled and specify the kind of visualization they should have (sprite, multiple sprites, particles, label, etc) as well as a list of components and initial data.

Which kind of game? Most likely a platformer according to roadmap votes. The runner-up (turn-based strategy / combat) would be a nice second example with which I can test pathfinding integration (again: not using GameplayKit but rather recast & detour or similar).

Later: Entering The Third Dimension?

The platformer game on an orthogonal map viewed from the side would also provide a great use case for adding the 3rd dimension to TilemapKit. How?

By porting the renderer to SceneKit and Cocos2d-x’ 3D nodes and generating cuboids from tiles, basically extruding tiles into the 3rd dimension (vote for this here).

I’m not giving a guarantee just yet but I’m positively surprised by the number of votes in such a short time. It would also allow games built with TilemapKit to truly stand out, with proper 3D camera and lighting, even 3D physics and who knows, perhaps even voxel characters.

I’m personally excited about doing this, it just seems awesome to be able to make a 3D game out of 2D tools and not having to work with a full-blown game framework such as Unity, or a complex 3D modelling program such as Blender.

Kickstarting Us

Okay, enough talking, back to programming. I wish I could just set marketing on autopilot but alas, I have to do that (this thing right here) as well. You can of course help me with that by tweeting and sharing this post, or just about anything related to TilemapKit.

Also, would you consider supporting me (actually: us) via Patreon?
Leave a comment or send us an email …

Patreon would mainly be a voluntary thing for TilemapKit enthusiasts as a way of helping us spend more time on TilemapKit. It would also serve as an ongoing Kickstarter, and reduce the need of having to do contract work on the sides. Maybe there’ll be an angle in terms of rewards too, although I admit I haven’t given this any thought yet.

Also, if you know someone who’s working in one of those secret human cloning facilities … please get in touch with us asap!

TilemapKit updated

I just now updated TilemapKit to v0.93 and TilemapKit++ to v0.75.

Specifically Cocos2d-x users should consider updating (or buying) TK++ v0.75 as it now has most of the features of the ObjC version.

You may also want to vote on the 3D tilemap renderer I’ve been contemplating about. That would go along nicely with the proposed Platformer StarterKit and enable you to create 3D games with relative ease.

TilemapKit++ (Cocos2d-x) now runs on Windows

Not that bad for a day of work. :)

Screen Shot 2015-10-09 at 22.08.33

So this is TilemapKit++ running on Windows 7 with Visual Studio 2015 (Community) and Cocos2d-x v3.8. The semi-transparancy is intentional (and correct).

An update for the current TilemapKit++ early access build is now imminent. Probably tomorrow if everything goes according to plan, otherwise tuesday. I’ll push an update for the ObjC version as well which will include a couple minor fixes.

PS: Here’s how to get this working with the (v0.75 or newer) early access version:

  • Add all source files located in the TilemapKit Framework folders: ModelCpp, NodesCocos2dx, pugixml and – unlike for other platforms – also add the zlib files.
  • Edit “Include Directories” to include the above folders.
  • #include "TKMapNode.hpp"

TilemapKit Render Size Demonstration

This video was recorded with the work-in-progress port of TilemapKit++ for Cocos2d-x. It illustrates how “render size” (draw only visible tiles) works.