Home

Awesome

Entity-Component-System Benchmarks

Actions Status License Standard

This repository contains a collection of benchmarks for popular Entity-Component-System (ECS) frameworks. The benchmarks cover different aspects of ECS frameworks, such as update systems, component additions/removals, and entity creation/destruction. It's important to note that different ECS frameworks have different strengths and weaknesses. For example, some frameworks might excel in adding/removing components, while others might be better at creating/destroying entities or have query support. Therefore, it's crucial to choose an ECS framework based on your specific requirements.

ECS (Entity-Component-System) Frameworks:

TL;DR Results

Main feature of an ECS is the iterating over a lot of entities and using system to update the components. The results of these benchmarks should be used as a starting point for your own benchmarking efforts.

Update systems (for-each entities (with mixed components) in 7 systems)

ComplexSystemsUpdateMixedEntities Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update 1 entities with 7 Systems123ns130ns89ns131ns48ns221ns1741ns67ns227ns225ns
Update 4 entities with 7 Systems223ns364ns138ns169ns106ns475ns2727ns125ns416ns394ns
Update 8 entities with 7 Systems310ns684ns203ns237ns173ns534ns2868ns209ns454ns454ns
Update 16 entities with 7 Systems348ns838ns207ns182ns205ns425ns2663ns209ns355ns332ns
Update 32 entities with 7 Systems574ns1622ns304ns237ns368ns520ns2810ns370ns419ns443ns
Update 64 entities with 7 Systems1038ns3052ns501ns353ns728ns661ns2960ns652ns560ns558ns
EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update 256 entities with 7 Systems7us21us4us4us4us2us4us5us2us2us
Update ~1K entities with 7 Systems31us91us18us21us16us7us10us19us9us10us
Update ~4K entities with 7 Systems138us374us89us103us68us27us30us91us45us45us
Update ~16K entities with 7 Systems569us1455us403us365us321us113us120us366us219us211us
EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update ~65K entities with 7 Systems2ms5ms1ms1ms1ms0ms0ms1ms1ms1ms
Update 262K entities with 7 Systems12ms24ms8ms6ms6ms3ms3ms6ms7ms7ms
Update ~1M entities with 7 Systems40ms102ms35ms26ms27ms16ms19ms25ms31ms32ms
Update ~2M entities with 7 Systems85ms184ms87ms51ms55ms33ms42ms53ms62ms69ms

While this benchmark only includes up to 6 components and 7 small systems, it's important to note that Entity-Component-Systems can become much more complex in the wild, with hundreds of components and systems. Therefore, it's crucial to always benchmark your specific cases and systems when necessary and compare results. Choose an ECS framework based on its features, for example, EnTT offers resource management and event handling, while flecs provides useful add-ons and querying, and EntityX includes a built-in world/system manager.

To evaluate a framework, look at the examples and API design, and pick the one that suits your needs.

Details

Features

All benchmarks are located in the benchmark/benchmarks/ directory and write with with the google/benchmark library. Each benchmark uses an example application for each framework (see src/ directory), and every example application has specific base features implemented (see src/base).

Components

  1. PositionComponent: includes x and y coordinates.
  2. VelocityComponent: includes x and y coordinates for movement.
  3. DataComponent: includes some arbitrary data.
  4. HealthComponent: Hero/Monster data includes HP/MaxHP and status.
  5. DamageComponent: Hero/Monster data includes damage.
  6. SpriteComponent: Hero/Monster ASCII character as sprite.

Systems

  1. MovementSystem: updates the PositionComponent with a constant VelocityComponent.
  2. DataSystem: updates the DataComponent with arbitrary data.
  3. MoreComplexSystem: updates components with random data and arbitrary information.
  4. HealthSystem: update Hero/Monster health (update HP and status).
  5. DamageSystem: update Hero/Monster health by taking damage.
  6. SpriteSystem: update Hero/Monster ASCII character depending on health and type.
  7. RenderSystem: "render"(write) Hero/Monster character sprite into a "frame buffer"(string buffer).

Additional Benchmarks

Benchmarks for more common features, such as "Creating entities", "Adding and removing components", and others.

Features tested

Environment


Create entities

CreateEntities Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Create 1 entities with two Components1368ns2881ns10449ns2327ns439949ns1331ns4683ns
Create 4 entities with two Components1816ns3155ns10119ns2692ns444861ns1315ns4901ns
Create 8 entities with two Components2245ns3461ns10313ns3086ns444572ns1426ns5522ns
Create 16 entities with two Components2995ns3812ns10869ns3654ns443523ns1555ns6458ns
Create 32 entities with two Components4233ns4419ns11265ns4838ns448326ns1875ns8323ns
Create 64 entities with two Components6848ns5706ns12227ns7042ns467177ns2499ns12369ns
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Create 256 entities with two Components21us13us16us20us535us6us36us
Create ~1K entities with two Components81us42us34us73us846us21us125us
Create ~4K entities with two Components318us161us101us283us1958us92us481us
Create ~16K entities with two Components1319us623us363us1109us6365us366us1924us
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Create ~65K entities with two Components4ms2ms1ms4ms22ms1ms8ms
Create 262K entities with two Components20ms10ms8ms18ms109ms6ms36ms
Create ~1M entities with two Components97ms68ms52ms90ms409ms48ms151ms
Create ~2M entities with two Components191ms133ms109ms175ms741ms77ms325ms

Destroy entities

DestroyEntities Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EntityXEnTTGinsengFlecspico_ecsgaia-ecs
Destroy 1 entities with two components1008ns904ns1056ns364035ns1208ns3074ns
Destroy 4 entities with two components1236ns1028ns1419ns363733ns1241ns3355ns
Destroy 8 entities with two components1366ns1196ns1975ns381173ns1267ns3751ns
Destroy 16 entities with two components1660ns1502ns2793ns371021ns1320ns4752ns
Destroy 32 entities with two components2394ns2139ns4419ns377250ns1438ns6833ns
Destroy 64 entities with two components3815ns3372ns7731ns376331ns1644ns10905ns
EntityXEnTTGinsengFlecspico_ecsgaia-ecs
Destroy 256 entities with two components12us11us28us383us2us32us
Destroy ~1K entities with two components48us40us105us415us8us121us
Destroy ~4K entities with two components201us157us434us590us32us487us
Destroy ~16K entities with two components812us627us1743us1243us122us2038us
EntityXEnTTGinsengFlecspico_ecsgaia-ecs
Destroy ~65K entities with two components3ms2ms6ms3ms0ms7ms
Destroy 262K entities with two components14ms10ms27ms17ms2ms35ms
Destroy ~1M entities with two components63ms43ms115ms60ms11ms178ms
Destroy ~2M entities with two components124ms86ms227ms118ms19ms398ms

Get one component from entity

UnpackOneComponent Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack one component in 1 entities3ns3ns1ns13ns13ns1ns2ns
Unpack one component in 4 entities14ns12ns7ns47ns57ns5ns10ns
Unpack one component in 8 entities28ns25ns13ns84ns112ns11ns20ns
Unpack one component in 16 entities57ns51ns28ns174ns212ns27ns40ns
Unpack one component in 32 entities115ns107ns59ns376ns415ns49ns84ns
Unpack one component in 64 entities231ns204ns118ns655ns856ns90ns164ns
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack one component in 256 entities0us0us0us2us3us0us0us
Unpack one component in ~1K entities3us3us1us10us12us1us2us
Unpack one component in ~4K entities14us12us7us44us51us5us10us
Unpack one component in ~16K entities59us51us28us203us210us21us42us
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack one component in ~65K entities0ms0ms0ms0ms0ms0ms0ms
Unpack one component in 262K entities1ms0ms0ms2ms3ms0ms0ms
Unpack one component in ~1M entities4ms3ms2ms11ms13ms1ms3ms
Unpack one component in ~2M entities9ms7ms4ms23ms26ms2ms8ms

Note:

Get two components from entity

UnpackTwoComponents Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack two components in 1 entities7ns6ns3ns23ns28ns2ns4ns
Unpack two components in 4 entities28ns25ns14ns98ns110ns11ns16ns
Unpack two components in 8 entities57ns55ns28ns190ns210ns21ns37ns
Unpack two components in 16 entities115ns104ns56ns364ns409ns48ns72ns
Unpack two components in 32 entities231ns212ns118ns730ns803ns89ns135ns
Unpack two components in 64 entities462ns468ns236ns1554ns1599ns171ns267ns
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack two components in 256 entities1us1us0us5us6us0us1us
Unpack two components in ~1K entities7us6us3us22us25us2us4us
Unpack two components in ~4K entities29us26us14us88us103us10us16us
Unpack two components in ~16K entities118us105us56us368us458us42us68us
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack two components in ~65K entities0ms0ms0ms1ms1ms0ms0ms
Unpack two components in 262K entities2ms1ms0ms6ms6ms0ms1ms
Unpack two components in ~1M entities9ms7ms3ms24ms26ms2ms5ms
Unpack two components in ~2M entities18ms14ms7ms50ms53ms5ms10ms

Note:

Get three components from entity

UnpackThreeComponents Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack three components in 1 entities7ns12ns6ns23ns59ns3ns9ns
Unpack three components in 2 entities14ns24ns12ns44ns125ns7ns17ns
Unpack three components in 8 entities57ns100ns48ns193ns449ns35ns75ns
Unpack three components in 16 entities115ns196ns97ns384ns888ns69ns142ns
Unpack three components in 32 entities231ns431ns195ns767ns1781ns121ns276ns
Unpack three components in 64 entities470ns795ns396ns1504ns3588ns237ns546ns
Unpack three components in 128 entities927ns1557ns841ns2826ns7121ns468ns1084ns
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack three components in 512 entities3us6us3us11us30us1us4us
Unpack three components in ~2K entities14us25us12us44us112us7us17us
Unpack three components in ~8K entities59us100us50us180us449us29us72us
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Unpack three components in ~32K entities0ms0ms0ms0ms1ms0ms0ms
Unpack three components in 131K entities1ms1ms0ms2ms7ms0ms1ms
Unpack three components in 524K entities4ms6ms3ms12ms28ms1ms5ms
Unpack three components in ~1M entities9ms14ms7ms25ms57ms3ms11ms

Note:

Remove and add component

RemoveAddComponent Plot

Graph shows cost per entity, tables shows total cost. lower is faster.

EntityXEnTTGinsengFlecspico_ecsgaia-ecs
Remove and Add a Component in 1 entities15ns24ns11ns246ns8ns130ns
Remove and Add a Component in 4 entities59ns109ns43ns957ns42ns535ns
Remove and Add a Component in 8 entities125ns204ns93ns1901ns69ns1057ns
Remove and Add a Component in 16 entities244ns396ns181ns3751ns132ns2108ns
Remove and Add a Component in 32 entities500ns785ns353ns7450ns256ns4192ns
Remove and Add a Component in 64 entities951ns1560ns703ns14853ns505ns8379ns
EntityXEnTTGinsengFlecspico_ecsgaia-ecs
Remove and Add a Component in 256 entities3us6us2us59us2us33us
Remove and Add a Component in ~1K entities15us25us11us236us8us134us
Remove and Add a Component in ~4K entities60us104us48us1004us32us536us
Remove and Add a Component in ~16K entities249us408us185us3890us129us2144us
EntityXEnTTGinsengFlecspico_ecsgaia-ecs
Remove and Add a Component in ~65K entities0ms1ms0ms15ms0ms8ms
Remove and Add a Component in 262K entities4ms6ms3ms62ms2ms34ms
Remove and Add a Component in ~1M entities16ms26ms12ms250ms8ms137ms
Remove and Add a Component in ~2M entities32ms53ms23ms527ms16ms277ms

Note:

Update systems (for-each entities in 2 systems)

Cost per entityCost of all entities
SystemsUpdate PlotSystemsUpdate Line Plot

Tables shows total cost. lower is faster.

EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Update 1 entities with 2 systems39ns27ns13ns68ns1287ns22ns100ns
Update 4 entities with 2 systems93ns55ns34ns90ns1262ns41ns91ns
Update 8 entities with 2 systems166ns99ns59ns94ns1279ns71ns107ns
Update 16 entities with 2 systems314ns161ns109ns122ns1309ns147ns133ns
Update 32 entities with 2 systems601ns294ns218ns173ns1358ns257ns188ns
Update 64 entities with 2 systems1171ns630ns429ns284ns1467ns490ns289ns
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Update 256 entities with 2 systems5us2us1us0us2us1us0us
Update ~1K entities with 2 systems18us8us6us3us4us7us3us
Update ~4K entities with 2 systems82us34us29us13us14us30us15us
Update ~16K entities with 2 systems315us140us127us56us56us165us65us
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Update ~65K entities with 2 systems1ms0ms0ms0ms0ms0ms0ms
Update 262K entities with 2 systems5ms2ms2ms1ms3ms2ms3ms
Update ~1M entities with 2 systems21ms12ms10ms8ms12ms12ms12ms
Update ~2M entities with 2 systems44ms25ms21ms15ms25ms22ms25ms

Note:

Update systems (for-each entities (with mixed components) in 2 systems)

Cost per entityCost of all entities
SystemsUpdateMixedEntities PlotSystemsUpdateMixedEntities Line Plot

Tables shows total cost. lower is faster.

EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Update 1 entities with 2 systems29ns16ns7ns36ns577ns16ns53ns
Update 4 entities with 2 systems75ns45ns28ns126ns1313ns34ns113ns
Update 8 entities with 2 systems137ns87ns51ns151ns1475ns55ns133ns
Update 16 entities with 2 systems266ns145ns94ns190ns1389ns95ns147ns
Update 32 entities with 2 systems534ns278ns198ns242ns1467ns194ns191ns
Update 64 entities with 2 systems1080ns555ns404ns357ns1583ns353ns300ns
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Update 256 entities with 2 systems4us2us1us1us2us1us1us
Update ~1K entities with 2 systems18us8us7us3us4us7us4us
Update ~4K entities with 2 systems82us32us28us14us15us41us15us
Update ~16K entities with 2 systems301us145us132us56us56us165us67us
EntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecs
Update ~65K entities with 2 systems1ms0ms0ms0ms0ms0ms0ms
Update 262K entities with 2 systems5ms3ms2ms1ms2ms2ms3ms
Update ~1M entities with 2 systems22ms13ms11ms7ms13ms11ms13ms
Update ~2M entities with 2 systems44ms30ms22ms15ms25ms24ms25ms

Note:

Update systems (for-each entities in 7 systems)

Cost per entityCost of all entities
ComplexSystemsUpdate PlotComplexSystemsUpdate Line Plot

Tables shows total cost. lower is faster.

EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update 1 entities with 7 systems138ns174ns93ns121ns51ns224ns2775ns70ns279ns275ns
Update 4 entities with 7 systems293ns525ns174ns239ns117ns274ns2584ns157ns335ns316ns
Update 8 entities with 7 systems479ns1016ns272ns351ns229ns357ns2626ns288ns384ns384ns
Update 16 entities with 7 systems755ns1963ns415ns560ns399ns394ns2630ns516ns490ns498ns
Update 32 entities with 7 systems1357ns3664ns775ns1050ns750ns540ns2777ns947ns627ns611ns
Update 64 entities with 7 systems2620ns7461ns1346ns2214ns1431ns860ns3079ns1808ns974ns932ns
EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update 256 entities with 7 systems10us28us5us9us5us2us4us6us3us3us
Update ~1K entities with 7 systems52us100us27us39us23us8us11us27us14us14us
Update ~4K entities with 7 systems202us493us132us172us102us37us39us106us72us73us
Update ~16K entities with 7 systems827us1947us592us651us445us158us189us469us362us347us
EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update ~65K entities with 7 systems3ms7ms2ms2ms1ms0ms0ms1ms1ms1ms
Update 262K entities with 7 systems16ms32ms12ms11ms8ms4ms6ms7ms10ms12ms
Update ~1M entities with 7 systems57ms122ms51ms45ms35ms21ms25ms31ms43ms43ms
Update ~2M entities with 7 systems112ms237ms127ms89ms70ms42ms52ms65ms84ms85ms

Note:

Update systems (for-each entities (with mixed components) in 7 systems)

Cost per entityCost of all entities
ComplexSystemsUpdateMixedEntities PlotComplexSystemsUpdateMixedEntities Line Plot

Tables shows total cost. lower is faster.

EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update 1 entities with 7 Systems123ns130ns89ns131ns48ns221ns1741ns67ns227ns225ns
Update 4 entities with 7 Systems223ns364ns138ns169ns106ns475ns2727ns125ns416ns394ns
Update 8 entities with 7 Systems310ns684ns203ns237ns173ns534ns2868ns209ns454ns454ns
Update 16 entities with 7 Systems348ns838ns207ns182ns205ns425ns2663ns209ns355ns332ns
Update 32 entities with 7 Systems574ns1622ns304ns237ns368ns520ns2810ns370ns419ns443ns
Update 64 entities with 7 Systems1038ns3052ns501ns353ns728ns661ns2960ns652ns560ns558ns
EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update 256 entities with 7 Systems7us21us4us4us4us2us4us5us2us2us
Update ~1K entities with 7 Systems31us91us18us21us16us7us10us19us9us10us
Update ~4K entities with 7 Systems138us374us89us103us68us27us30us91us45us45us
Update ~16K entities with 7 Systems569us1455us403us365us321us113us120us366us219us211us
EnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)
Update ~65K entities with 7 Systems2ms5ms1ms1ms1ms0ms0ms1ms1ms1ms
Update 262K entities with 7 Systems12ms24ms8ms6ms6ms3ms3ms6ms7ms7ms
Update ~1M entities with 7 Systems40ms102ms35ms26ms27ms16ms19ms25ms31ms32ms
Update ~2M entities with 7 Systems85ms184ms87ms51ms55ms33ms42ms53ms62ms69ms

Note:

Contributing

If you have any improvements to the ECS-examples for any of the frameworks, feel free to make a pull request or open an issue. The example(s) for each framework can be found in src/, and benchmarks are located in benchmarks/benchmarks/ for more details.

Additionally, you can write tests for the framework example and add some metadata to the plot.config.json file. Any contributions are greatly appreciated!

TODO: make more detailed "how to add framework"

Read CONTRIBUTING.md for more details.

Run Benchmarks

Using Taskfile

  1. Install Taskfile
  2. Run Build: task build
  3. Run (All) Benchmarks: task benchmark
  4. Plot Graphs: task plot:all

Or run task generate

You can now find the benchmark-results in reports/.

You need python (>=3.8.0) and some dependencies to run gen-benchmark-report (plotting), install pipx and poetry.

Then install the dependencies for the script:

cd ./scripts/gen-benchmark-report && poetry install

Or run the script directly:

task plot:all

Generate README

task generate:readme

Step-by-Step

  1. Configure and build benchmarks, see Building Details:
    1. cmake -S . -B ./build
    2. cmake --build ./build
  2. Run benchmark(s), with run-benchmarks.sh or each:
    • ./build/benchmark/benchmarks/entt/ecs-benchmark-entt (console output) (optional)
    • ./build/benchmark/benchmarks/entt/ecs-benchmark-entt --benchmark_format=json > ./reports/entt.json (write json report)
  3. Plot Reports, after generating json reports, see plot-results.sh:
    1. pipx run --spec ./scripts/gen-benchmark-report gen-benchmark-report -i ./info.json gen-plot ./reports/entityx.json ./reports/entt.json ./reports/ginseng.json ./reports/mustache.json ./reports/openecs.json ./reports/flecs.json (generate graphs)
    2. pipx run --spec ./scripts/gen-benchmark-report gen-benchmark-report -i ./info.json gen-results-md ./reports/entityx.json ./reports/entt.json ./reports/ginseng.json ./reports/mustache.json ./reports/openecs.json ./reports/flecs.json (generate full report)

Run a single benchmark

cmake -G Ninja -S . -B build
cmake --build build --target ecs-benchmark-entt -j 4
./build/benchmark/benchmarks/entt/ecs-benchmark-entt

You can use -DCMAKE_BUILD_TYPE=Debug to enable Sanitizers.

Links and More

Candidates

EntityX by @alecthomas

Entity Component Systems (ECS) are a form of decomposition that completely decouples entity logic and data from the entity "objects" themselves. The Evolve your Hierarchy article provides a solid overview of EC systems and why you should use them.

Version: 1.1.2 (Apr 2023)

EnTT by @skypjack

EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.

Version: v3.13.2

Ginseng by @apples

Ginseng is an entity-component-system (ECS) library designed for use in games.

The main advantage over similar libraries is that the component types do not need to be listed or registered. Component types are detected dynamically.

Any function-like object can be used as a system. The function's parameters are used to determine the required components.

Version: 1.1 (Dec 2021)

mustache by @kirillochnev

A fast, modern C++ Entity Component System

Version: 0.2 (Feb 2024)

OpenEcs by @Gronis

Open Ecs is an Entity Component System that uses metaprogramming, cache coherency, and other useful tricks to maximize performance and configurability. It is written in c++11 without further dependencies.

Version: 0.1.101 (Apr 2017)

Flecs by @SanderMertens

Flecs is a fast and lightweight Entity Component System that lets you build games and simulations with millions of entities.

Version: v4.0.1

pico_ecs by @empyreanx

A collection of cross-platform single header libraries written in C. Pure and simple ECS.

Version: 2.3 (Sep 2023)

gaia-ecs by @richardbiely

Gaia-ECS is a fast and easy-to-use ECS framework.

Version: v0.8.6