diff --git a/CMakeLists.txt b/CMakeLists.txt index 0289544..58c4be5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ run_vcpkg() # Set the project name and language project( ecs-benchmark - VERSION 4.7.4 + VERSION 5.0.0 DESCRIPTION "Benchmarks of common ECS (Entity-Component-System)-Frameworks in C++ (or C)" HOMEPAGE_URL "https://github.com/abeimler/ecs_benchmark" LANGUAGES CXX C) diff --git a/README.md b/README.md index b6b9d37..f31a212 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,11 @@ ![License](https://img.shields.io/github/license/abeimler/ecs_benchmark) ![Standard](https://img.shields.io/badge/c%2B%2B-20-blue) -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. -Each benchmark is performed on three simple components and three small systems, which can be scaled to hundreds of components and systems in a real-world scenario. The results of the benchmarks are displayed in tables and charts, allowing you to compare the performance of different ECS frameworks in different areas. -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. Therefore, it's crucial to choose an ECS framework based on your specific requirements. +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. +Therefore, it's crucial to choose an ECS framework based on your specific requirements. ECS (Entity-Component-System) Frameworks: @@ -19,43 +21,45 @@ ECS (Entity-Component-System) Frameworks: ## TL;DR Results -The benchmark results are displayed in tables and charts, -allowing you to quickly compare the performance of different ECS frameworks in different scenarios. The tables include the time in nanoseconds it takes to perform the benchmark on different numbers of entities, -while the charts provide a visual representation of the results. -When using ECS frameworks, it's important to benchmark your specific use case and compare the results. +The benchmark results are displayed in tables and charts, +allowing you to quickly compare the performance of different ECS frameworks in different scenarios. +When using ECS frameworks, it's important to benchmark your specific use case and compare the results. Therefore, 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 3 systems) +### Update systems (for-each entities (with mixed components) in 5 systems) + ![ComplexSystemsUpdateMixedEntities Plot](img/ComplexSystemsUpdateMixedEntities.svg) _(lower is better)_ -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:---------|:-----------------|:----------------|:----------------|:----------|:--------------|:------------|:------------| -| Update 16 entities with 3 Systems | 1460ns | 1988ns | 1333ns | 1362ns | 1392ns | 26458ns | 2831ns | **1141ns** | -| Update 64 entities with 3 Systems | 5949ns | 8268ns | 5592ns | 5644ns | 5881ns | 30455ns | 7307ns | **4583ns** | -| Update 256 entities with 3 Systems | 25396ns | 37313ns | **24138ns** | 23515ns | 25675ns | 47928ns | 26465ns | 25937ns | -| Update ~1K entities with 3 Systems | 98721ns | 145130ns | **93535ns** | 96784ns | 99236ns | 115345ns | 97519ns | 102751ns | -| Update ~4K entities with 3 Systems | 389719ns | 579405ns | 375206ns | **359119ns** | 393509ns | 386604ns | 377360ns | 418940ns | - -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:-----------|:----------------|:---------------|:----------------|:------------|:------------|:------------|:------------| -| Update ~16K entities with 3 Systems | **1ms** | 2ms | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | -| Update ~65K entities with 3 Systems | 6ms | 9ms | **5ms** | **5ms** | 6ms | **5ms** | **5ms** | 6ms | -| Update 262K entities with 3 Systems | 25ms | 36ms | **24ms** | **24ms** | 25ms | 26ms | **24ms** | **24ms** | -| Update ~1M entities with 3 Systems | 100ms | 145ms | 106ms | **94ms** | 101ms | 95ms | 96ms | 98ms | -| Update ~2M entities with 3 Systems | 199ms | 291ms | 273ms | 198ms | 202ms | **192ms** | 195ms | 200ms | - - -While this benchmark only includes three simple components and three 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. +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:----------|:----------------|:----------------|:---------------|:----------|:-----------|:--------|:-----------| +| Update 16 entities with 5 Systems | **1us** | 2us | **1us** | **1us** | **1us** | 43us | 3us | **1us** | +| Update 64 entities with 5 Systems | 6us | 9us | **5us** | **5us** | 6us | 49us | 7us | **5us** | +| Update 256 entities with 5 Systems | 26us | 40us | 25us | **24us** | 25us | 64us | 26us | 26us | +| Update ~1K entities with 5 Systems | 105us | 158us | 100us | **96us** | 100us | 136us | 99us | 102us | +| Update ~4K entities with 5 Systems | 415us | 630us | 398us | **381us** | 395us | 416us | 383us | 408us | + +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:----------|:---------------|:--------------|:--------------|:-----------|:--------------|:---------|:-----------| +| Update ~16K entities with 5 Systems | **1ms** | 2ms | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | +| Update ~65K entities with 5 Systems | 6ms | 10ms | 6ms | 6ms | 6ms | **5ms** | 6ms | 6ms | +| Update 262K entities with 5 Systems | 26ms | 40ms | 26ms | 25ms | 26ms | **24ms** | 25ms | 26ms | +| Update ~1M entities with 5 Systems | 105ms | 160ms | 114ms | 101ms | 105ms | **97ms** | 100ms | 105ms | +| Update ~2M entities with 5 Systems | 211ms | 321ms | 277ms | 204ms | 213ms | **195ms** | 200ms | 212ms | + + + +While this benchmark only includes up to 5 simple components and 5 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. -Different ECS frameworks excel in different areas, such as faster adding/removing of components or creating/destroying entities. -Therefore, it's essential to choose an ECS framework based on its features. -For example, EnTT offers [resource management](https://github.com/skypjack/entt/wiki/Crash-Course:-resource-management) and [event handling](https://github.com/skypjack/entt/wiki/Crash-Course:-events,-signals-and-everything-in-between), while flecs provides useful [add-ons](https://github.com/SanderMertens/flecs#addons), and EntityX includes a built-in [world/system manager](https://github.com/alecthomas/entityx#manager-tying-it-all-together=). +Choose an ECS framework based on its features, +for example, EnTT offers [resource management](https://github.com/skypjack/entt/wiki/Crash-Course:-resource-management) and [event handling](https://github.com/skypjack/entt/wiki/Crash-Course:-events,-signals-and-everything-in-between), +while flecs provides useful [add-ons](https://github.com/SanderMertens/flecs#addons), +and EntityX includes a built-in [world/system manager](https://github.com/alecthomas/entityx#manager-tying-it-all-together=). To evaluate a framework, look at its examples and API design, and pick the one that suits your needs the best. @@ -64,8 +68,8 @@ To evaluate a framework, look at its examples and API design, and pick the one t ### Features -All benchmarks are located in the [`benchmark/benchmarks/`](benchmark/benchmarks/) directory and are implemented with the [google/benchmark](https://github.com/google/benchmark) library. -Each benchmark must implement the `ECSBenchmark.h` template. +All benchmarks are located in the [`benchmark/benchmarks/`](benchmark/benchmarks/) directory and are implemented with the [google/benchmark](https://github.com/google/benchmark) library. +Each benchmark must implement the `ECSBenchmark.h` template. Each framework has its own sub-project in the [`src/`](src) directory and must implement specific features (see [`src/base`](src/base)). @@ -74,12 +78,17 @@ Each framework has its own sub-project in the [`src/`](src) directory and must i 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. #### 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. + ## Additional Benchmarks @@ -111,21 +120,21 @@ Benchmarks for more common features, such as "Creating entities", "Adding and re _(lower is better)_ -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:------------------------------------------|:----------|:---------|:----------|:----------|:----------|:-------------| -| Create 16 entities with two Components | 3123ns | 3909ns | 10943ns | 3476ns | 514606ns | **1472ns** | -| Create 64 entities with two Components | 7108ns | 5840ns | 12606ns | 7484ns | 555455ns | **2441ns** | -| Create 256 entities with two Components | 22722ns | 12838ns | 18445ns | 21230ns | 581109ns | **5409ns** | -| Create ~1K entities with two Components | 85253ns | 38584ns | 35607ns | 74202ns | 748617ns | **19907ns** | -| Create ~4K entities with two Components | 372921ns | 141231ns | 106427ns | 287775ns | 1625498ns | **83456ns** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Create 16 entities with two Components | 2us | 3us | 10us | 3us | 509us | 1us | +| Create 64 entities with two Components | 6us | 5us | 12us | 6us | 519us | 2us | +| Create 256 entities with two Components | 20us | 12us | 17us | 19us | 574us | 6us | +| Create ~1K entities with two Components | 75us | 41us | 34us | 70us | 759us | 20us | +| Create ~4K entities with two Components | 297us | 139us | 102us | 276us | 1544us | 89us | -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:------------------------------------------|:----------|:----------|:-----------|:----------|:--------|:-------------| -| Create ~16K entities with two Components | 1ms | **0ms** | **0ms** | 1ms | 5ms | **0ms** | -| Create ~65K entities with two Components | 5ms | 2ms | **1ms** | 4ms | 17ms | **1ms** | -| Create 262K entities with two Components | 21ms | 11ms | 9ms | 18ms | 64ms | **6ms** | -| Create ~1M entities with two Components | 103ms | 57ms | 59ms | 92ms | 290ms | **34ms** | -| Create ~2M entities with two Components | 208ms | 118ms | 110ms | 182ms | 569ms | **69ms** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Create ~16K entities with two Components | 1ms | 0ms | 0ms | 1ms | 4ms | 0ms | +| Create ~65K entities with two Components | 4ms | 2ms | 1ms | 4ms | 17ms | 1ms | +| Create 262K entities with two Components | 18ms | 9ms | 8ms | 18ms | 65ms | 7ms | +| Create ~1M entities with two Components | 100ms | 76ms | 59ms | 99ms | 301ms | 46ms | +| Create ~2M entities with two Components | 197ms | 139ms | 110ms | 195ms | 586ms | 80ms | @@ -136,21 +145,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | -|:-------------------------------------------|:----------|:---------|:----------|:---------|:--------------| -| Destroy 16 entities with two components | 1679ns | 1562ns | 2417ns | 454230ns | **1269ns** | -| Destroy 64 entities with two components | 3729ns | 3268ns | 6026ns | 458514ns | **1547ns** | -| Destroy 256 entities with two components | 12446ns | 8980ns | 20788ns | 538117ns | **2557ns** | -| Destroy ~1K entities with two components | 47944ns | 33813ns | 76495ns | 524592ns | **5928ns** | -| Destroy ~4K entities with two components | 194775ns | 131020ns | 306243ns | 775907ns | **22274ns** | +| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | +|:-------------------------------------------|:----------|:-------|:----------|:--------|:-----------| +| Destroy 16 entities with two components | 1us | 1us | 2us | 462us | 1us | +| Destroy 64 entities with two components | 3us | 2us | 6us | 461us | 1us | +| Destroy 256 entities with two components | 12us | 8us | 23us | 474us | 2us | +| Destroy ~1K entities with two components | 48us | 30us | 90us | 516us | 7us | +| Destroy ~4K entities with two components | 196us | 120us | 357us | 677us | 28us | -| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | -|:-------------------------------------------|:-------------|:----------|:----------|:--------|:-------------| -| Destroy ~16K entities with two components | **0ms** | **0ms** | 1ms | 1ms | **0ms** | -| Destroy ~65K entities with two components | 3ms | 2ms | 5ms | 4ms | **0ms** | -| Destroy 262K entities with two components | 13ms | 8ms | 19ms | 14ms | **1ms** | -| Destroy ~1M entities with two components | 63ms | 36ms | 85ms | 62ms | **9ms** | -| Destroy ~2M entities with two components | 125ms | 72ms | 168ms | 126ms | **15ms** | +| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | +|:-------------------------------------------|:----------|:-------|:----------|:--------|:-----------| +| Destroy ~16K entities with two components | 0ms | 0ms | 1ms | 1ms | 0ms | +| Destroy ~65K entities with two components | 3ms | 1ms | 5ms | 4ms | 0ms | +| Destroy 262K entities with two components | 13ms | 8ms | 23ms | 14ms | 1ms | +| Destroy ~1M entities with two components | 63ms | 36ms | 101ms | 63ms | 9ms | +| Destroy ~2M entities with two components | 128ms | 74ms | 195ms | 122ms | 18ms | @@ -161,21 +170,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:---------------------------------------|:----------|:--------|:----------|:-----------|:---------|:-------------| -| Unpack one component in 16 entities | 22ns | 54ns | 28ns | 200ns | 659ns | **26ns** | -| Unpack one component in 64 entities | 100ns | 221ns | 114ns | 819ns | 2422ns | **91ns** | -| Unpack one component in 256 entities | 362ns | 878ns | 445ns | 3158ns | 9770ns | **339ns** | -| Unpack one component in ~1K entities | 1441ns | 3511ns | 1786ns | 11721ns | 40790ns | **1356ns** | -| Unpack one component in ~4K entities | 5662ns | 13834ns | 7097ns | 46167ns | 156085ns | **5583ns** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:---------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Unpack one component in 16 entities | 0us | 0us | 0us | 0us | 0us | 0us | +| Unpack one component in 64 entities | 0us | 0us | 0us | 0us | 2us | 0us | +| Unpack one component in 256 entities | 0us | 0us | 0us | 2us | 9us | 0us | +| Unpack one component in ~1K entities | 3us | 3us | 1us | 10us | 38us | 1us | +| Unpack one component in ~4K entities | 14us | 13us | 6us | 43us | 154us | 5us | -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:---------------------------------------|:------------|:----------|:----------|:-----------|:-----------|:-----------| -| Unpack one component in ~16K entities | **0ms** | **0ms** | **0ms** | **0ms** | **0ms** | **0ms** | -| Unpack one component in ~65K entities | **0ms** | **0ms** | **0ms** | **0ms** | 2ms | **0ms** | -| Unpack one component in 262K entities | **0ms** | **0ms** | **0ms** | 4ms | 10ms | **0ms** | -| Unpack one component in ~1M entities | **1ms** | 3ms | 2ms | 18ms | 40ms | **1ms** | -| Unpack one component in ~2M entities | 3ms | 7ms | 3ms | 29ms | 80ms | **2ms** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:---------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Unpack one component in ~16K entities | 0ms | 0ms | 0ms | 0ms | 0ms | 0ms | +| Unpack one component in ~65K entities | 0ms | 0ms | 0ms | 0ms | 2ms | 0ms | +| Unpack one component in 262K entities | 1ms | 0ms | 0ms | 3ms | 10ms | 0ms | +| Unpack one component in ~1M entities | 4ms | 3ms | 1ms | 15ms | 39ms | 1ms | +| Unpack one component in ~2M entities | 10ms | 6ms | 3ms | 30ms | 79ms | 2ms | **Note:** @@ -190,21 +199,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:----------------------------------------|:-------------|:--------|:----------|:-----------|:---------|:-------------| -| Unpack two components in 16 entities | 48ns | 108ns | 59ns | 358ns | 1314ns | **47ns** | -| Unpack two components in 64 entities | **174ns** | 431ns | 248ns | 1450ns | 5133ns | **174ns** | -| Unpack two components in 256 entities | 698ns | 1663ns | 1003ns | 6020ns | 19974ns | **674ns** | -| Unpack two components in ~1K entities | 2754ns | 6648ns | 3606ns | 22481ns | 81667ns | **2664ns** | -| Unpack two components in ~4K entities | 10867ns | 26748ns | 14452ns | 91050ns | 323314ns | **10633ns** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:----------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Unpack two components in 16 entities | 0us | 0us | 0us | 0us | 1us | 0us | +| Unpack two components in 64 entities | 0us | 0us | 0us | 1us | 4us | 0us | +| Unpack two components in 256 entities | 1us | 1us | 0us | 5us | 19us | 0us | +| Unpack two components in ~1K entities | 7us | 6us | 2us | 22us | 79us | 2us | +| Unpack two components in ~4K entities | 29us | 25us | 12us | 88us | 317us | 10us | -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:----------------------------------------|:------------|:----------|:------------|:------------|:--------|:----------| -| Unpack two components in ~16K entities | **0ms** | **0ms** | **0ms** | **0ms** | 1ms | **0ms** | -| Unpack two components in ~65K entities | **0ms** | **0ms** | **0ms** | 1ms | 5ms | **0ms** | -| Unpack two components in 262K entities | **0ms** | 1ms | 1ms | 6ms | 20ms | **0ms** | -| Unpack two components in ~1M entities | **2ms** | 7ms | 3ms | 26ms | 80ms | **2ms** | -| Unpack two components in ~2M entities | **5ms** | 14ms | 8ms | 50ms | 161ms | **5ms** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:----------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Unpack two components in ~16K entities | 0ms | 0ms | 0ms | 0ms | 1ms | 0ms | +| Unpack two components in ~65K entities | 0ms | 0ms | 0ms | 1ms | 5ms | 0ms | +| Unpack two components in 262K entities | 2ms | 1ms | 0ms | 6ms | 20ms | 0ms | +| Unpack two components in ~1M entities | 8ms | 6ms | 3ms | 27ms | 80ms | 2ms | +| Unpack two components in ~2M entities | 18ms | 13ms | 6ms | 49ms | 161ms | 5ms | @@ -221,21 +230,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:------------------------------------------|:------------|:--------|:--------|:-----------|:---------|:-------------| -| Unpack three components in 8 entities | **33ns** | 123ns | 50ns | 186ns | 977ns | **35ns** | -| Unpack three components in 32 entities | 125ns | 470ns | 206ns | 770ns | 3985ns | **123ns** | -| Unpack three components in 128 entities | 505ns | 1899ns | 808ns | 2827ns | 15417ns | **475ns** | -| Unpack three components in 512 entities | 2069ns | 7343ns | 3395ns | 11470ns | 62415ns | **1883ns** | -| Unpack three components in ~2K entities | 8513ns | 29829ns | 13996ns | 50784ns | 247313ns | **7512ns** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Unpack three components in 8 entities | 0us | 0us | 0us | 0us | 0us | 0us | +| Unpack three components in 32 entities | 0us | 0us | 0us | 0us | 3us | 0us | +| Unpack three components in 128 entities | 0us | 1us | 0us | 2us | 15us | 0us | +| Unpack three components in 512 entities | 3us | 7us | 2us | 11us | 60us | 1us | +| Unpack three components in ~2K entities | 14us | 28us | 11us | 44us | 241us | 7us | -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:------------------------------------------|:-----------|:----------|:-----------|:-----------|:--------|:-----------| -| Unpack three components in ~8K entities | **0ms** | **0ms** | **0ms** | **0ms** | 1ms | **0ms** | -| Unpack three components in ~32K entities | **0ms** | **0ms** | **0ms** | **0ms** | 3ms | **0ms** | -| Unpack three components in 131K entities | **0ms** | 1ms | **0ms** | 3ms | 16ms | **0ms** | -| Unpack three components in 524K entities | 2ms | 7ms | 3ms | 12ms | 65ms | **1ms** | -| Unpack three components in ~1M entities | 4ms | 15ms | 9ms | 28ms | 137ms | **3ms** | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Unpack three components in ~8K entities | 0ms | 0ms | 0ms | 0ms | 0ms | 0ms | +| Unpack three components in ~32K entities | 0ms | 0ms | 0ms | 0ms | 3ms | 0ms | +| Unpack three components in 131K entities | 1ms | 1ms | 0ms | 3ms | 15ms | 0ms | +| Unpack three components in 524K entities | 4ms | 7ms | 3ms | 12ms | 62ms | 2ms | +| Unpack three components in ~1M entities | 9ms | 15ms | 6ms | 25ms | 125ms | 4ms | @@ -254,21 +263,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | -|:---------------------------------------------|:----------|:---------|:----------|:---------|:-------------| -| Remove and Add a Component in 16 entities | 246ns | 421ns | 194ns | 3656ns | **143ns** | -| Remove and Add a Component in 64 entities | 970ns | 1668ns | 763ns | 15013ns | **566ns** | -| Remove and Add a Component in 256 entities | 4064ns | 6480ns | 3042ns | 58247ns | **2155ns** | -| Remove and Add a Component in ~1K entities | 16273ns | 26029ns | 13282ns | 233165ns | **8608ns** | -| Remove and Add a Component in ~4K entities | 65497ns | 104614ns | 52822ns | 968833ns | **37276ns** | +| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | +|:---------------------------------------------|:----------|:-------|:----------|:--------|:-----------| +| Remove and Add a Component in 16 entities | 0us | 0us | 0us | 3us | 0us | +| Remove and Add a Component in 64 entities | 0us | 1us | 0us | 14us | 0us | +| Remove and Add a Component in 256 entities | 3us | 6us | 2us | 57us | 2us | +| Remove and Add a Component in ~1K entities | 23us | 27us | 15us | 226us | 8us | +| Remove and Add a Component in ~4K entities | 62us | 108us | 46us | 903us | 34us | -| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | -|:---------------------------------------------|:------------|:---------|:------------|:-------|:-----------| -| Remove and Add a Component in ~16K entities | **0ms** | **0ms** | **0ms** | 4ms | **0ms** | -| Remove and Add a Component in ~65K entities | 1ms | 1ms | **0ms** | 16ms | **0ms** | -| Remove and Add a Component in 262K entities | 4ms | 6ms | 3ms | 60ms | **2ms** | -| Remove and Add a Component in ~1M entities | 16ms | 26ms | 12ms | 260ms | **8ms** | -| Remove and Add a Component in ~2M entities | 32ms | 53ms | 24ms | 518ms | **19ms** | +| | EntityX | EnTT | Ginseng | Flecs | pico_ecs | +|:---------------------------------------------|:----------|:-------|:----------|:--------|:-----------| +| Remove and Add a Component in ~16K entities | 0ms | 0ms | 0ms | 3ms | 0ms | +| Remove and Add a Component in ~65K entities | 0ms | 1ms | 0ms | 14ms | 0ms | +| Remove and Add a Component in 262K entities | 4ms | 7ms | 3ms | 57ms | 2ms | +| Remove and Add a Component in ~1M entities | 16ms | 30ms | 12ms | 230ms | 8ms | +| Remove and Add a Component in ~2M entities | 32ms | 60ms | 24ms | 457ms | 17ms | @@ -284,21 +293,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:----------|:------------|:------------|:--------------|:---------|:----------| -| Update 16 entities with 2 systems | 1787ns | **1530ns** | 1544ns | 17463ns | 2638ns | 1577ns | -| Update 64 entities with 2 systems | 7394ns | **5956ns** | 6163ns | 22125ns | 7382ns | 6529ns | -| Update 256 entities with 2 systems | 28879ns | **23526ns** | 24570ns | 39892ns | 27542ns | 24648ns | -| Update ~1K entities with 2 systems | 112575ns | 98369ns | **97617ns** | 102707ns | 108173ns | 103970ns | -| Update ~4K entities with 2 systems | 458125ns | 362088ns | 392786ns | **359513ns** | 429106ns | 393898ns | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Update 16 entities with 2 systems | 1us | 1us | 1us | 16us | 2us | 1us | +| Update 64 entities with 2 systems | 7us | 6us | 6us | 21us | 7us | 6us | +| Update 256 entities with 2 systems | 28us | 23us | 24us | 39us | 25us | 24us | +| Update ~1K entities with 2 systems | 121us | 96us | 96us | 110us | 94us | 93us | +| Update ~4K entities with 2 systems | 441us | 370us | 382us | 386us | 368us | 367us | -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:------------|:----------|:----------|:-------------|:----------|:------------| -| Update ~16K entities with 2 systems | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | -| Update ~65K entities with 2 systems | 7ms | **5ms** | 6ms | **5ms** | 6ms | 6ms | -| Update 262K entities with 2 systems | 29ms | 23ms | 25ms | **22ms** | 25ms | 26ms | -| Update ~1M entities with 2 systems | 115ms | 93ms | 109ms | **91ms** | 107ms | 100ms | -| Update ~2M entities with 2 systems | 226ms | 186ms | 194ms | **185ms** | 197ms | 214ms | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Update ~16K entities with 2 systems | 1ms | 1ms | 1ms | 1ms | 1ms | 1ms | +| Update ~65K entities with 2 systems | 6ms | 6ms | 6ms | 6ms | 5ms | 5ms | +| Update 262K entities with 2 systems | 28ms | 23ms | 24ms | 24ms | 23ms | 23ms | +| Update ~1M entities with 2 systems | 113ms | 92ms | 96ms | 98ms | 94ms | 93ms | +| Update ~2M entities with 2 systems | 231ms | 185ms | 193ms | 196ms | 190ms | 190ms | @@ -315,21 +324,21 @@ _(lower is better)_ _(lower is better)_ -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:----------|:------------|:----------|:--------------|:---------|:------------| -| Update 16 entities with 2 systems | 1627ns | 1351ns | 1379ns | 17884ns | 2678ns | **1088ns** | -| Update 64 entities with 2 systems | 6589ns | 5479ns | 5843ns | 22473ns | 7075ns | **4365ns** | -| Update 256 entities with 2 systems | 28393ns | **23773ns** | 25667ns | 38445ns | 27896ns | 24901ns | -| Update ~1K entities with 2 systems | 111353ns | **92429ns** | 100518ns | 105287ns | 99573ns | 99346ns | -| Update ~4K entities with 2 systems | 440921ns | 363872ns | 391112ns | **363471ns** | 401103ns | 388733ns | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Update 16 entities with 2 systems | 1us | 1us | 1us | 18us | 2us | 1us | +| Update 64 entities with 2 systems | 6us | 5us | 5us | 23us | 6us | 4us | +| Update 256 entities with 2 systems | 28us | 23us | 25us | 39us | 25us | 24us | +| Update ~1K entities with 2 systems | 110us | 91us | 98us | 111us | 94us | 93us | +| Update ~4K entities with 2 systems | 439us | 365us | 387us | 387us | 368us | 367us | -| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:-------------|:----------|:-------------|:------------|:--------|:-----------| -| Update ~16K entities with 2 systems | **1ms** | **1ms** | **1ms** | **1ms** | 2ms | **1ms** | -| Update ~65K entities with 2 systems | 7ms | **5ms** | 6ms | 6ms | 6ms | 6ms | -| Update 262K entities with 2 systems | 27ms | 23ms | 24ms | **22ms** | 25ms | 26ms | -| Update ~1M entities with 2 systems | 112ms | 95ms | 98ms | **91ms** | 101ms | 105ms | -| Update ~2M entities with 2 systems | 241ms | 193ms | 191ms | **183ms** | 199ms | 217ms | +| | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------| +| Update ~16K entities with 2 systems | 1ms | 1ms | 1ms | 1ms | 1ms | 1ms | +| Update ~65K entities with 2 systems | 6ms | 5ms | 6ms | 6ms | 5ms | 5ms | +| Update 262K entities with 2 systems | 28ms | 23ms | 24ms | 24ms | 23ms | 23ms | +| Update ~1M entities with 2 systems | 112ms | 93ms | 97ms | 98ms | 94ms | 92ms | +| Update ~2M entities with 2 systems | 232ms | 185ms | 194ms | 197ms | 189ms | 186ms | **Note:** @@ -339,28 +348,28 @@ _(lower is better)_ * Not every entity has all three components, some got removed -### Update systems (for-each entities in 3 systems) +### Update systems (for-each entities in 5 systems) ![ComplexSystemsUpdate Plot](img/ComplexSystemsUpdate.svg) _(lower is better)_ -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:---------|:-----------------|:------------------|:-------------------|:----------|:-----------|:---------|:-----------| -| Update 16 entities with 3 systems | 1643ns | 2362ns | **1531ns** | 1545ns | 1607ns | 24329ns | 2917ns | 1647ns | -| Update 64 entities with 3 systems | 6828ns | 9267ns | 6465ns | **6054ns** | 6388ns | 29074ns | 7747ns | 6523ns | -| Update 256 entities with 3 systems | 25800ns | 36985ns | 24142ns | **23717ns** | 25569ns | 46420ns | 26757ns | 26216ns | -| Update ~1K entities with 3 systems | 98987ns | 146332ns | 94552ns | **90570ns** | 99574ns | 113073ns | 98074ns | 102292ns | -| Update ~4K entities with 3 systems | 386503ns | 576164ns | 374139ns | **360864ns** | 394419ns | 381801ns | 379212ns | 403493ns | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------| +| Update 16 entities with 5 systems | 1us | 2us | 1us | 1us | 1us | 39us | 3us | 1us | +| Update 64 entities with 5 systems | 6us | 11us | 6us | 6us | 6us | 44us | 7us | 6us | +| Update 256 entities with 5 systems | 27us | 44us | 25us | 25us | 26us | 62us | 26us | 26us | +| Update ~1K entities with 5 systems | 109us | 180us | 102us | 99us | 101us | 133us | 99us | 105us | +| Update ~4K entities with 5 systems | 434us | 719us | 404us | 399us | 417us | 414us | 386us | 416us | -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:---------|:---------------|:----------------|:------------------|:------------|:------------|:-----------|:-----------| -| Update ~16K entities with 3 systems | **1ms** | 2ms | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | -| Update ~65K entities with 3 systems | 6ms | 9ms | 5ms | 5ms | 6ms | 5ms | 5ms | 6ms | -| Update 262K entities with 3 systems | 25ms | 36ms | 24ms | 24ms | 25ms | 24ms | 24ms | 26ms | -| Update ~1M entities with 3 systems | 99ms | 145ms | 104ms | 95ms | 100ms | 95ms | 95ms | 100ms | -| Update ~2M entities with 3 systems | 203ms | 290ms | 226ms | 191ms | 202ms | 190ms | 192ms | 204ms | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------| +| Update ~16K entities with 5 systems | 1ms | 2ms | 1ms | 1ms | 1ms | 1ms | 1ms | 1ms | +| Update ~65K entities with 5 systems | 6ms | 11ms | 6ms | 6ms | 6ms | 6ms | 6ms | 6ms | +| Update 262K entities with 5 systems | 27ms | 45ms | 27ms | 26ms | 27ms | 25ms | 25ms | 26ms | +| Update ~1M entities with 5 systems | 112ms | 181ms | 126ms | 107ms | 111ms | 100ms | 102ms | 107ms | +| Update ~2M entities with 5 systems | 225ms | 363ms | 288ms | 217ms | 220ms | 197ms | 206ms | 217ms | @@ -369,6 +378,8 @@ _(lower is better)_ 1. `MovementSystem` 2. `DataSystem` 3. `MoreComplexSystem` + 4. `HealthSystem` + 5. `DamageSystem` * \* EnTT iterate components via [views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#views=) * \** EnTT iterate components via [runtime views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#runtime-views=) * \*** EnTT iterate components via [groups](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#groups=): @@ -380,28 +391,28 @@ _(lower is better)_ -### Update systems (for-each entities (with mixed components) in 3 systems) +### Update systems (for-each entities (with mixed components) in 5 systems) ![ComplexSystemsUpdateMixedEntities Plot](img/ComplexSystemsUpdateMixedEntities.svg) _(lower is better)_ -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:---------|:----------------|:-----------------|:-------------------|:----------|:-----------|:---------|:--------------| -| Update 16 entities with 3 Systems | 1460ns | 1988ns | 1333ns | 1362ns | 1392ns | 26458ns | 2831ns | **1141ns** | -| Update 64 entities with 3 Systems | 5949ns | 8268ns | 5592ns | 5644ns | 5881ns | 30455ns | 7307ns | **4583ns** | -| Update 256 entities with 3 Systems | 25396ns | 37313ns | 24138ns | **23515ns** | 25675ns | 47928ns | 26465ns | 25937ns | -| Update ~1K entities with 3 Systems | 98721ns | 145130ns | **93535ns** | 96784ns | 99236ns | 115345ns | 97519ns | 102751ns | -| Update ~4K entities with 3 Systems | 389719ns | 579405ns | 375206ns | **359119ns** | 393509ns | 386604ns | 377360ns | 418940ns | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------| +| Update 16 entities with 5 Systems | 1us | 2us | 1us | 1us | 1us | 43us | 3us | 1us | +| Update 64 entities with 5 Systems | 6us | 9us | 5us | 5us | 6us | 49us | 7us | 5us | +| Update 256 entities with 5 Systems | 26us | 40us | 25us | 24us | 25us | 64us | 26us | 26us | +| Update ~1K entities with 5 Systems | 105us | 158us | 100us | 96us | 100us | 136us | 99us | 102us | +| Update ~4K entities with 5 Systems | 415us | 630us | 398us | 381us | 395us | 416us | 383us | 408us | -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | -|:-------------------------------------|:----------|:---------------|:---------------|:--------------|:-----------|:--------------|:--------------|:------------| -| Update ~16K entities with 3 Systems | **1ms** | 2ms | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | **1ms** | -| Update ~65K entities with 3 Systems | 6ms | 9ms | **5ms** | **5ms** | 6ms | **5ms** | **5ms** | 6ms | -| Update 262K entities with 3 Systems | 25ms | 36ms | **24ms** | **24ms** | 25ms | 26ms | **24ms** | **24ms** | -| Update ~1M entities with 3 Systems | 100ms | 145ms | 106ms | **94ms** | 101ms | 95ms | 96ms | 98ms | -| Update ~2M entities with 3 Systems | 199ms | 291ms | 273ms | 198ms | 202ms | **192ms** | 195ms | 200ms | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------| +| Update ~16K entities with 5 Systems | 1ms | 2ms | 1ms | 1ms | 1ms | 1ms | 1ms | 1ms | +| Update ~65K entities with 5 Systems | 6ms | 10ms | 6ms | 6ms | 6ms | 5ms | 6ms | 6ms | +| Update 262K entities with 5 Systems | 26ms | 40ms | 26ms | 25ms | 26ms | 24ms | 25ms | 26ms | +| Update ~1M entities with 5 Systems | 105ms | 160ms | 114ms | 101ms | 105ms | 97ms | 100ms | 105ms | +| Update ~2M entities with 5 Systems | 211ms | 321ms | 277ms | 204ms | 213ms | 195ms | 200ms | 212ms | @@ -410,6 +421,8 @@ _(lower is better)_ 1. `MovementSystem` 2. `DataSystem` 3. `MoreComplexSystem` + 4. `HealthSystem` + 5. `DamageSystem` * Not every entity has all three components, some got removed * \* EnTT iterate components via [views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#views=) * \** EnTT iterate components via [runtime views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#runtime-views=) @@ -420,15 +433,13 @@ _(lower is better)_ * \**** EnTT iterate components via view and uses a [stable component](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#pointer-stability=) (`StablePositionComponent`) -Here's an improved version of the "Contributing" section: - ## 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. +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/`](src/), and benchmarks are located in [`benchmarks/benchmarks/`](benchmarks/benchmarks/) for more details. -Additionally, you can write tests for the framework example and add some metadata to the [plot.config.json](plot.config.json) file. +Additionally, you can write tests for the framework example and add some metadata to the [plot.config.json](plot.config.json) file. Any contributions are greatly appreciated! _TODO: make more detailed "how to add framework"_ @@ -494,7 +505,7 @@ Version: v3.12.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. diff --git a/README.md.mustache b/README.md.mustache index dc3fee6..851e111 100644 --- a/README.md.mustache +++ b/README.md.mustache @@ -4,9 +4,11 @@ ![License](https://img.shields.io/github/license/abeimler/ecs_benchmark) ![Standard](https://img.shields.io/badge/c%2B%2B-20-blue) -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. -Each benchmark is performed on three simple components and three small systems, which can be scaled to hundreds of components and systems in a real-world scenario. The results of the benchmarks are displayed in tables and charts, allowing you to compare the performance of different ECS frameworks in different areas. -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. Therefore, it's crucial to choose an ECS framework based on your specific requirements. +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. +Therefore, it's crucial to choose an ECS framework based on your specific requirements. ECS (Entity-Component-System) Frameworks: @@ -20,23 +22,24 @@ ECS (Entity-Component-System) Frameworks: ## TL;DR Results The benchmark results are displayed in tables and charts, -allowing you to quickly compare the performance of different ECS frameworks in different scenarios. The tables include the time in nanoseconds it takes to perform the benchmark on different numbers of entities, -while the charts provide a visual representation of the results. +allowing you to quickly compare the performance of different ECS frameworks in different scenarios. When using ECS frameworks, it's important to benchmark your specific use case and compare the results. Therefore, 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 3 systems) + +### Update systems (for-each entities (with mixed components) in 5 systems) {{{ComplexSystemsUpdateMixedEntities}}} -While this benchmark only includes three simple components and three small systems, +While this benchmark only includes up to 5 simple components and 5 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. -Different ECS frameworks excel in different areas, such as faster adding/removing of components or creating/destroying entities. -Therefore, it's essential to choose an ECS framework based on its features. -For example, EnTT offers [resource management](https://github.com/skypjack/entt/wiki/Crash-Course:-resource-management) and [event handling](https://github.com/skypjack/entt/wiki/Crash-Course:-events,-signals-and-everything-in-between), while flecs provides useful [add-ons](https://github.com/SanderMertens/flecs#addons), and EntityX includes a built-in [world/system manager](https://github.com/alecthomas/entityx#manager-tying-it-all-together=). +Choose an ECS framework based on its features, +for example, EnTT offers [resource management](https://github.com/skypjack/entt/wiki/Crash-Course:-resource-management) and [event handling](https://github.com/skypjack/entt/wiki/Crash-Course:-events,-signals-and-everything-in-between), +while flecs provides useful [add-ons](https://github.com/SanderMertens/flecs#addons), +and EntityX includes a built-in [world/system manager](https://github.com/alecthomas/entityx#manager-tying-it-all-together=). To evaluate a framework, look at its examples and API design, and pick the one that suits your needs the best. @@ -52,15 +55,19 @@ Each framework has its own sub-project in the [`src/`](src) directory and must i #### Components -1. `PositionComponent` with `x` and `y` coord. -2. `VelocityComponent` with `x` and `y` for movement. -3. `DataComponent` with some nonsense data. +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. #### Systems -1. `MovementSystem`: updates `PositionComponent` with (const) `VelocityComponent` -2. `DataSystem`: updates `DataComponent` with nonsense -3. `MoreComplexSystem`: updates Components with random data and nonsense +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. ## Additional Benchmarks @@ -162,7 +169,7 @@ Benchmarks for more common features, such as "Creating entities", "Adding and re * Not every entity has all three components, some got removed -### Update systems (for-each entities in 3 systems) +### Update systems (for-each entities in 5 systems) {{{ComplexSystemsUpdate}}} @@ -172,6 +179,8 @@ Benchmarks for more common features, such as "Creating entities", "Adding and re 1. `MovementSystem` 2. `DataSystem` 3. `MoreComplexSystem` + 4. `HealthSystem` + 5. `DamageSystem` * \* EnTT iterate components via [views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#views=) * \** EnTT iterate components via [runtime views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#runtime-views=) * \*** EnTT iterate components via [groups](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#groups=): @@ -183,7 +192,7 @@ Benchmarks for more common features, such as "Creating entities", "Adding and re -### Update systems (for-each entities (with mixed components) in 3 systems) +### Update systems (for-each entities (with mixed components) in 5 systems) {{{ComplexSystemsUpdateMixedEntities}}} @@ -193,6 +202,8 @@ Benchmarks for more common features, such as "Creating entities", "Adding and re 1. `MovementSystem` 2. `DataSystem` 3. `MoreComplexSystem` + 4. `HealthSystem` + 5. `DamageSystem` * Not every entity has all three components, some got removed * \* EnTT iterate components via [views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#views=) * \** EnTT iterate components via [runtime views](https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#runtime-views=) diff --git a/VERSION b/VERSION index b48b2de..0062ac9 100755 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.7.4 +5.0.0 diff --git a/benchmark/benchmarks/BaseECSBenchmark.h b/benchmark/benchmarks/BaseECSBenchmark.h index 2a5da17..eb608f2 100644 --- a/benchmark/benchmarks/BaseECSBenchmark.h +++ b/benchmark/benchmarks/BaseECSBenchmark.h @@ -53,6 +53,8 @@ class BaseECSBenchmark { state.counters["components_one"] = static_cast(components_counter.component_one_count); state.counters["components_two"] = static_cast(components_counter.component_two_count); state.counters["components_three"] = static_cast(components_counter.component_three_count); + state.counters["hero_count"] = static_cast(components_counter.hero_count); + state.counters["monster_count"] = static_cast(components_counter.monster_count); } diff --git a/benchmark/benchmarks/ECSBenchmark.h b/benchmark/benchmarks/ECSBenchmark.h index 2e99736..6100228 100644 --- a/benchmark/benchmarks/ECSBenchmark.h +++ b/benchmark/benchmarks/ECSBenchmark.h @@ -3,6 +3,7 @@ #include "BaseECSBenchmark.h" #include "EntityBenchmark.h" +#include "base/components/HeroMonsterComponents.h" #include "basic.h" #include #include @@ -14,7 +15,10 @@ namespace ecs::benchmarks::base { -template +enum class ECSBenchmarkIncludeEntityBenchmarks : bool { No = false, Yes = true }; + +template class ECSBenchmark : protected BaseECSBenchmark { public: using EntityManager = typename EntityFactory::EntityManager; @@ -65,7 +69,22 @@ class ECSBenchmark : protected BaseECSBenchmark { const auto nentities = static_cast(state.range(0)); std::vector entities; Application app(m_options.add_more_complex_system); - const ComponentsCounter components_counter = this->initApplicationWithEntities(app, nentities, entities); + ComponentsCounter components_counter = this->initApplicationWithEntities(app, nentities, entities); + for (auto entity : entities) { + using namespace ecs::benchmarks::base::components; + m_hero_monster_entities_factory.addComponents(app.getEntities(), entity); + const auto type = m_hero_monster_entities_factory.initComponents(app.getEntities(), entity); + switch (type) { + case PlayerType::Hero: + components_counter.hero_count++; + break; + case PlayerType::Monster: + components_counter.monster_count++; + break; + case PlayerType::NPC: + break; + } + } for (auto _ : state) { app.update(fakeTimeDelta); } @@ -78,8 +97,39 @@ class ECSBenchmark : protected BaseECSBenchmark { const auto nentities = static_cast(state.range(0)); std::vector entities; Application app(m_options.add_more_complex_system); - const ComponentsCounter components_counter = + ComponentsCounter components_counter = this->template initApplicationWithMixedComponents(app, nentities, entities); + for (size_t i = 0, j = 0; i < entities.size(); i++) { + auto entity = entities[i]; + if (nentities >= 100 || i >= nentities / 8) { + if (nentities >= 100 || (j % 2) == 0U) { + using namespace ecs::benchmarks::base::components; + if ((i % 6) == 0U) { + m_hero_monster_entities_factory.addComponents(app.getEntities(), entity); + const auto type = m_hero_monster_entities_factory.initComponents(app.getEntities(), entity); + switch (type) { + case PlayerType::Hero: + components_counter.hero_count++; + break; + case PlayerType::Monster: + components_counter.monster_count++; + break; + case PlayerType::NPC: + break; + } + } else if ((i % 4) == 0U) { + m_hero_monster_entities_factory.addComponents(app.getEntities(), entity); + m_hero_monster_entities_factory.initComponents(app.getEntities(), entity, PlayerType::Hero); + components_counter.hero_count++; + } else if ((i % 2) == 0U) { + m_hero_monster_entities_factory.addComponents(app.getEntities(), entity); + m_hero_monster_entities_factory.initComponents(app.getEntities(), entity, PlayerType::Monster); + components_counter.monster_count++; + } + } + j++; + } + } for (auto _ : state) { app.update(fakeTimeDelta); } @@ -90,7 +140,7 @@ class ECSBenchmark : protected BaseECSBenchmark { template - requires include_entity_benchmarks + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes) void BM_CreateNoEntities(benchmark::State& state) { const auto nentities = 0; for (auto _ : state) { @@ -107,7 +157,7 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes) void BM_CreateEmptyEntities(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); for (auto _ : state) { @@ -124,7 +174,7 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks && HasBulkFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && HasBulkFeature) void BM_CreateEmptyEntitiesInBulk(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); for (auto _ : state) { @@ -141,7 +191,7 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes) void BM_CreateEntities(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); for (auto _ : state) { @@ -158,7 +208,8 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks && HasBulkFeatureWithOutput + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasBulkFeatureWithOutput) void BM_CreateEntitiesInBulk(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); for (auto _ : state) { @@ -176,7 +227,7 @@ class ECSBenchmark : protected BaseECSBenchmark { template - requires include_entity_benchmarks && HasDestroyFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && HasDestroyFeature) void BM_DestroyEntities(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); for (auto _ : state) { @@ -202,7 +253,8 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks && HasBulkDestroyFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasBulkDestroyFeature) void BM_DestroyEntitiesInBulk(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); for (auto _ : state) { @@ -221,7 +273,8 @@ class ECSBenchmark : protected BaseECSBenchmark { template - requires include_entity_benchmarks && HasGetComponentsFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasGetComponentsFeature) void BM_UnpackNoComponent(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); Application app(m_options.add_more_complex_system); @@ -239,7 +292,8 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks && HasGetComponentsFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasGetComponentsFeature) void BM_UnpackOneComponent_NoEntities(benchmark::State& state) { const auto nentities = 0; Application app(m_options.add_more_complex_system); @@ -257,7 +311,8 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks && HasGetComponentsFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasGetComponentsFeature) void BM_UnpackOneComponent(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); Application app(m_options.add_more_complex_system); @@ -275,8 +330,8 @@ class ECSBenchmark : protected BaseECSBenchmark { } // template - // requires include_entity_benchmarks && HasGetComponentsFeature - // void BM_UnpackOneConstComponent(benchmark::State& state) { + // requires (include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + // HasGetComponentsFeature) void BM_UnpackOneConstComponent(benchmark::State& state) { // const auto nentities = static_cast(state.range(0)); // Application app(m_options.add_more_complex_system); // EntityManager& registry = app.getEntities(); @@ -293,7 +348,8 @@ class ECSBenchmark : protected BaseECSBenchmark { // } template - requires include_entity_benchmarks && HasGetComponentsFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasGetComponentsFeature) void BM_UnpackTwoComponents(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); Application app(m_options.add_more_complex_system); @@ -312,7 +368,8 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks && HasGetComponentsFeature + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && + HasGetComponentsFeature) void BM_UnpackThreeComponents(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); Application app(m_options.add_more_complex_system); @@ -331,7 +388,7 @@ class ECSBenchmark : protected BaseECSBenchmark { } template - requires include_entity_benchmarks + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes) void BM_RemoveAddComponent(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); Application app(m_options.add_more_complex_system); @@ -424,6 +481,7 @@ class ECSBenchmark : protected BaseECSBenchmark { inline static constexpr auto m_name{Name.value}; const ESCBenchmarkOptions m_options; EntityFactory m_entities_factory; + HeroMonsterEntityFactory m_hero_monster_entities_factory; }; } // namespace ecs::benchmarks::base diff --git a/benchmark/benchmarks/ExtendedECSBenchmark.h b/benchmark/benchmarks/ExtendedECSBenchmark.h index 7ae4bc5..3ffa9dd 100644 --- a/benchmark/benchmarks/ExtendedECSBenchmark.h +++ b/benchmark/benchmarks/ExtendedECSBenchmark.h @@ -14,8 +14,10 @@ concept HasForEach = requires(Iterable it, Func func) { it.for_each(func); }; template concept HasVisit = requires(Iterable it, Func func) { it.visit(func); }; -template -class ExtendedECSBenchmark : public ECSBenchmark { +template +class ExtendedECSBenchmark + : public ECSBenchmark { private: inline static constexpr auto default_initializable_entity_manager = std::default_initializable; @@ -26,7 +28,7 @@ class ExtendedECSBenchmark : public ECSBenchmark(std::move(options)) {} + : ECSBenchmark(std::move(options)) {} virtual ~ExtendedECSBenchmark() = default; ExtendedECSBenchmark(const ExtendedECSBenchmark&) = default; ExtendedECSBenchmark& operator=(const ExtendedECSBenchmark&) = default; diff --git a/benchmark/benchmarks/basic.h b/benchmark/benchmarks/basic.h index a5b5193..0357d02 100644 --- a/benchmark/benchmarks/basic.h +++ b/benchmark/benchmarks/basic.h @@ -29,6 +29,9 @@ struct ComponentsCounter { size_t component_one_count{0}; size_t component_two_count{0}; size_t component_three_count{0}; + + size_t hero_count{0}; + size_t monster_count{0}; }; inline static constexpr auto MIN_ENTITIES_RANGE = 8L; diff --git a/benchmark/benchmarks/entityx-entities/EntityXEntityBenchmarkSuite.h b/benchmark/benchmarks/entityx-entities/EntityXEntityBenchmarkSuite.h index eb641e2..e15e7ca 100644 --- a/benchmark/benchmarks/entityx-entities/EntityXEntityBenchmarkSuite.h +++ b/benchmark/benchmarks/entityx-entities/EntityXEntityBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "entityx/EntityXApplication.h" #include "entityx/entities/EntityFactory.h" +#include "entityx/entities/HeroMonsterEntityFactory.h" #include @@ -14,10 +15,10 @@ namespace ecs::benchmarks::entityx { class EntityXEntityBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"entityx", EntityXApplication, entities::EntityFactory, - /*include_entity_benchmarks= */ true // application is needed to get - // entity manager - > { + : public ecs::benchmarks::base::ECSBenchmark< + "entityx", EntityXApplication, entities::EntityFactory, entities::HeroMonsterEntityFactory, + base::ECSBenchmarkIncludeEntityBenchmarks::Yes // application is needed to get entity manager + > { public: EntityXEntityBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entityx-extended/EntityXBenchmarkSuite.h b/benchmark/benchmarks/entityx-extended/EntityXBenchmarkSuite.h index 4d52694..f92cd26 100644 --- a/benchmark/benchmarks/entityx-extended/EntityXBenchmarkSuite.h +++ b/benchmark/benchmarks/entityx-extended/EntityXBenchmarkSuite.h @@ -3,6 +3,7 @@ #include "entityx/EntityXApplication.h" #include "entityx/entities/EntityFactory.h" +#include "entityx/entities/HeroMonsterEntityFactory.h" #include "entityx/systems/DataSystem.h" #include "entityx/systems/MoreComplexSystem.h" #include "entityx/systems/MovementSystem.h" @@ -18,7 +19,8 @@ namespace ecs::benchmarks::entityx { class EntityXBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"entityx", EntityXApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entityx", EntityXApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: EntityXBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entityx/EntityXBenchmarkSuite.h b/benchmark/benchmarks/entityx/EntityXBenchmarkSuite.h index b9c89a7..9ef87ca 100644 --- a/benchmark/benchmarks/entityx/EntityXBenchmarkSuite.h +++ b/benchmark/benchmarks/entityx/EntityXBenchmarkSuite.h @@ -3,6 +3,7 @@ #include "entityx/EntityXApplication.h" #include "entityx/entities/EntityFactory.h" +#include "entityx/entities/HeroMonsterEntityFactory.h" #include #include "ECSBenchmark.h" @@ -15,7 +16,8 @@ namespace ecs::benchmarks::entityx { class EntityXBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"entityx", EntityXApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"entityx", EntityXApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: EntityXBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h index 26c6851..01c5106 100644 --- a/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h @@ -4,12 +4,14 @@ #include "ExtendedECSBenchmark.h" #include "entt/EnttApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt", EnttApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt", EnttApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: EnttBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttFullOwningGroupBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttFullOwningGroupBenchmarkSuite.h index 1234772..9f8ed24 100644 --- a/benchmark/benchmarks/entt-extended/EnttFullOwningGroupBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttFullOwningGroupBenchmarkSuite.h @@ -4,13 +4,14 @@ #include "ExtendedECSBenchmark.h" #include "entt/EnttGroupApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttFullOwningGroupBenchmarkSuite final : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (group, full-owning)", EnttGroupApplication, - entities::EntityFactory> { + entities::EntityFactory, entities::HeroMonsterEntityFactory> { public: EnttFullOwningGroupBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttGroupBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttGroupBenchmarkSuite.h index 15284d3..9700ae9 100644 --- a/benchmark/benchmarks/entt-extended/EnttGroupBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttGroupBenchmarkSuite.h @@ -4,13 +4,14 @@ #include "ExtendedECSBenchmark.h" #include "entt/EnttGroupApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttGroupBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (group)", EnttGroupApplication, - entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (group)", EnttGroupApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: EnttGroupBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttNonOwningGroupBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttNonOwningGroupBenchmarkSuite.h index 06f8ace..6fec680 100644 --- a/benchmark/benchmarks/entt-extended/EnttNonOwningGroupBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttNonOwningGroupBenchmarkSuite.h @@ -4,13 +4,14 @@ #include "ExtendedECSBenchmark.h" #include "entt/EnttGroupApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttNonOwningGroupBenchmarkSuite final : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (group, non-owning)", EnttGroupApplication, - entities::EntityFactory> { + entities::EntityFactory, entities::HeroMonsterEntityFactory> { public: EnttNonOwningGroupBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttPartialOwningGroupBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttPartialOwningGroupBenchmarkSuite.h index 4e96a7a..dceddaf 100644 --- a/benchmark/benchmarks/entt-extended/EnttPartialOwningGroupBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttPartialOwningGroupBenchmarkSuite.h @@ -4,13 +4,14 @@ #include "ExtendedECSBenchmark.h" #include "entt/EnttGroupApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttPartialOwningGroupBenchmarkSuite final : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (group, partial-owning)", EnttGroupApplication, - entities::EntityFactory> { + entities::EntityFactory, entities::HeroMonsterEntityFactory> { public: EnttPartialOwningGroupBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttRuntimeBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttRuntimeBenchmarkSuite.h index 54f696d..2c47cb8 100644 --- a/benchmark/benchmarks/entt-extended/EnttRuntimeBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttRuntimeBenchmarkSuite.h @@ -4,13 +4,14 @@ #include "ExtendedECSBenchmark.h" #include "entt/EnttRuntimeApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttRuntimeBenchmarkSuite final : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (runtime)", EnttRuntimeApplication, - entities::EntityFactory> { + entities::EntityFactory, entities::HeroMonsterEntityFactory> { public: EnttRuntimeBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt-extended/EnttStableBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttStableBenchmarkSuite.h index 9d88a5c..fd26155 100644 --- a/benchmark/benchmarks/entt-extended/EnttStableBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttStableBenchmarkSuite.h @@ -3,14 +3,15 @@ #include "ExtendedECSBenchmark.h" #include "entt/StableEnttApplication.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include "entt/entities/StableEntityFactory.h" #include namespace ecs::benchmarks::entt { class EnttStableBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (stable)", StableEnttApplication, - entities::StableEntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark< + "entt (stable)", StableEnttApplication, entities::StableEntityFactory, entities::HeroMonsterEntityFactory> { public: EnttStableBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/entt/EnttBenchmarkSuite.h b/benchmark/benchmarks/entt/EnttBenchmarkSuite.h index f22002f..715e5f9 100644 --- a/benchmark/benchmarks/entt/EnttBenchmarkSuite.h +++ b/benchmark/benchmarks/entt/EnttBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "entt/EnttApplication.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include "entt/systems/DataSystem.h" #include "entt/systems/MoreComplexSystem.h" #include "entt/systems/MovementSystem.h" @@ -13,7 +14,8 @@ namespace ecs::benchmarks::entt { class EnttBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"entt", EnttApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"entt", EnttApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: EnttBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/flecs-extended/FlecsBenchmarkSuite.h b/benchmark/benchmarks/flecs-extended/FlecsBenchmarkSuite.h index 8ae9e1a..967e448 100644 --- a/benchmark/benchmarks/flecs-extended/FlecsBenchmarkSuite.h +++ b/benchmark/benchmarks/flecs-extended/FlecsBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ExtendedECSBenchmark.h" #include "flecs/FlecsApplication.h" #include "flecs/entities/EntityFactory.h" +#include "flecs/entities/HeroMonsterEntityFactory.h" #include "flecs/systems/DataSystem.h" #include "flecs/systems/MoreComplexSystem.h" #include "flecs/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::flecs { class FlecsBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"flecs", FlecsApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"flecs", FlecsApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: FlecsBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/flecs/FlecsBenchmarkSuite.h b/benchmark/benchmarks/flecs/FlecsBenchmarkSuite.h index f7a9f6b..e594f7f 100644 --- a/benchmark/benchmarks/flecs/FlecsBenchmarkSuite.h +++ b/benchmark/benchmarks/flecs/FlecsBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "flecs/FlecsApplication.h" #include "flecs/entities/EntityFactory.h" +#include "flecs/entities/HeroMonsterEntityFactory.h" #include "flecs/systems/DataSystem.h" #include "flecs/systems/MoreComplexSystem.h" #include "flecs/systems/MovementSystem.h" @@ -13,7 +14,8 @@ namespace ecs::benchmarks::flecs { class FlecsBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"flecs", FlecsApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"flecs", FlecsApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: FlecsBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/ginseng-extended/GinsengBenchmark.h b/benchmark/benchmarks/ginseng-extended/GinsengBenchmark.h index 6209b4e..a36880f 100644 --- a/benchmark/benchmarks/ginseng-extended/GinsengBenchmark.h +++ b/benchmark/benchmarks/ginseng-extended/GinsengBenchmark.h @@ -4,6 +4,7 @@ #include "ExtendedECSBenchmark.h" #include "ginseng/GinsengApplication.h" #include "ginseng/entities/EntityFactory.h" +#include "ginseng/entities/HeroMonsterEntityFactory.h" #include "ginseng/systems/DataSystem.h" #include "ginseng/systems/MoreComplexSystem.h" #include "ginseng/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::ginseng { class GinsengBenchmark final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"ginseng", GinsengApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"ginseng", GinsengApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: GinsengBenchmark() = default; diff --git a/benchmark/benchmarks/ginseng/GinsengBenchmark.h b/benchmark/benchmarks/ginseng/GinsengBenchmark.h index facc491..d4ba64e 100644 --- a/benchmark/benchmarks/ginseng/GinsengBenchmark.h +++ b/benchmark/benchmarks/ginseng/GinsengBenchmark.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "ginseng/GinsengApplication.h" #include "ginseng/entities/EntityFactory.h" +#include "ginseng/entities/HeroMonsterEntityFactory.h" #include "ginseng/systems/DataSystem.h" #include "ginseng/systems/MoreComplexSystem.h" #include "ginseng/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::ginseng { class GinsengBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"ginseng", GinsengApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"ginseng", GinsengApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: GinsengBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/mustache-entities/MustacheEntityBenchmarkSuite.h b/benchmark/benchmarks/mustache-entities/MustacheEntityBenchmarkSuite.h index 9c70344..3062cf7 100644 --- a/benchmark/benchmarks/mustache-entities/MustacheEntityBenchmarkSuite.h +++ b/benchmark/benchmarks/mustache-entities/MustacheEntityBenchmarkSuite.h @@ -4,15 +4,16 @@ #include "ECSBenchmark.h" #include "mustache/MustacheApplication.h" #include "mustache/entities/EntityFactory.h" +#include "mustache/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::mustache { class MustacheEntityBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"mustache", MustacheApplication, entities::EntityFactory, - /*include_entity_benchmarks= */ true // application is needed to get - // entity manager - > { + : public ecs::benchmarks::base::ECSBenchmark< + "mustache", MustacheApplication, entities::EntityFactory, entities::HeroMonsterEntityFactory, + base::ECSBenchmarkIncludeEntityBenchmarks::Yes // application is needed to get entity manager + > { public: MustacheEntityBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/mustache-extended/MustacheBenchmarkSuite.h b/benchmark/benchmarks/mustache-extended/MustacheBenchmarkSuite.h index ce52718..af72cc2 100644 --- a/benchmark/benchmarks/mustache-extended/MustacheBenchmarkSuite.h +++ b/benchmark/benchmarks/mustache-extended/MustacheBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ExtendedECSBenchmark.h" #include "mustache/MustacheApplication.h" #include "mustache/entities/EntityFactory.h" +#include "mustache/entities/HeroMonsterEntityFactory.h" #include "mustache/systems/DataSystem.h" #include "mustache/systems/MoreComplexSystem.h" #include "mustache/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::mustache { class MustacheBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"mustache", MustacheApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"mustache", MustacheApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: MustacheBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/mustache/MustacheBenchmarkSuite.h b/benchmark/benchmarks/mustache/MustacheBenchmarkSuite.h index d29018c..350e3c0 100644 --- a/benchmark/benchmarks/mustache/MustacheBenchmarkSuite.h +++ b/benchmark/benchmarks/mustache/MustacheBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "mustache/MustacheApplication.h" #include "mustache/entities/EntityFactory.h" +#include "mustache/entities/HeroMonsterEntityFactory.h" #include "mustache/systems/DataSystem.h" #include "mustache/systems/MoreComplexSystem.h" #include "mustache/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::mustache { class MustacheBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"mustache", MustacheApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"mustache", MustacheApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: MustacheBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/openecs-extended/OpenECSBenchmarkSuite.h b/benchmark/benchmarks/openecs-extended/OpenECSBenchmarkSuite.h index a5414d4..900faad 100644 --- a/benchmark/benchmarks/openecs-extended/OpenECSBenchmarkSuite.h +++ b/benchmark/benchmarks/openecs-extended/OpenECSBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ExtendedECSBenchmark.h" #include "openecs/OpenECSApplication.h" #include "openecs/entities/EntityFactory.h" +#include "openecs/entities/HeroMonsterEntityFactory.h" #include "openecs/systems/DataSystem.h" #include "openecs/systems/MoreComplexSystem.h" #include "openecs/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::openecs { class OpenECSBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"openecs", OpenECSApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"openecs", OpenECSApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: OpenECSBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/openecs/OpenECSBenchmarkSuite.h b/benchmark/benchmarks/openecs/OpenECSBenchmarkSuite.h index 0fc6caa..03a5727 100644 --- a/benchmark/benchmarks/openecs/OpenECSBenchmarkSuite.h +++ b/benchmark/benchmarks/openecs/OpenECSBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "openecs/OpenECSApplication.h" #include "openecs/entities/EntityFactory.h" +#include "openecs/entities/HeroMonsterEntityFactory.h" #include "openecs/systems/DataSystem.h" #include "openecs/systems/MoreComplexSystem.h" #include "openecs/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::openecs { class OpenECSBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"openecs", OpenECSApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"openecs", OpenECSApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: OpenECSBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/pico-ecs-entities/PicoEcsEntityBenchmarkSuite.h b/benchmark/benchmarks/pico-ecs-entities/PicoEcsEntityBenchmarkSuite.h index f8408b3..9770e07 100644 --- a/benchmark/benchmarks/pico-ecs-entities/PicoEcsEntityBenchmarkSuite.h +++ b/benchmark/benchmarks/pico-ecs-entities/PicoEcsEntityBenchmarkSuite.h @@ -4,15 +4,16 @@ #include "ECSBenchmark.h" #include "pico_ecs/PicoEcsApplication.h" #include "pico_ecs/entities/EntityFactory.h" +#include "pico_ecs/entities/HeroMonsterEntityFactory.h" #include namespace ecs::benchmarks::pico_ecs { class PicoEcsEntityBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"pico_ecs", PicoEcsApplication, entities::EntityFactory, - /*include_entity_benchmarks= */ true // application is needed to get - // entity manager - > { + : public ecs::benchmarks::base::ECSBenchmark< + "pico_ecs", PicoEcsApplication, entities::EntityFactory, entities::HeroMonsterEntityFactory, + base::ECSBenchmarkIncludeEntityBenchmarks::Yes // application is needed to get entity manager + > { public: PicoEcsEntityBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/pico-ecs-extended/PicoEcsBenchmarkSuite.h b/benchmark/benchmarks/pico-ecs-extended/PicoEcsBenchmarkSuite.h index a41717f..4bcbb74 100644 --- a/benchmark/benchmarks/pico-ecs-extended/PicoEcsBenchmarkSuite.h +++ b/benchmark/benchmarks/pico-ecs-extended/PicoEcsBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ExtendedECSBenchmark.h" #include "pico_ecs/PicoEcsApplication.h" #include "pico_ecs/entities/EntityFactory.h" +#include "pico_ecs/entities/HeroMonsterEntityFactory.h" #include "pico_ecs/systems/DataSystem.h" #include "pico_ecs/systems/MoreComplexSystem.h" #include "pico_ecs/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::pico_ecs { class PicoEcsBenchmarkSuite final - : public ecs::benchmarks::base::ExtendedECSBenchmark<"pico_ecs", PicoEcsApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ExtendedECSBenchmark<"pico_ecs", PicoEcsApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: PicoEcsBenchmarkSuite() = default; diff --git a/benchmark/benchmarks/pico-ecs/PicoEcsBenchmarkSuite.h b/benchmark/benchmarks/pico-ecs/PicoEcsBenchmarkSuite.h index bf93fcb..dac01de 100644 --- a/benchmark/benchmarks/pico-ecs/PicoEcsBenchmarkSuite.h +++ b/benchmark/benchmarks/pico-ecs/PicoEcsBenchmarkSuite.h @@ -4,6 +4,7 @@ #include "ECSBenchmark.h" #include "pico_ecs/PicoEcsApplication.h" #include "pico_ecs/entities/EntityFactory.h" +#include "pico_ecs/entities/HeroMonsterEntityFactory.h" #include "pico_ecs/systems/DataSystem.h" #include "pico_ecs/systems/MoreComplexSystem.h" #include "pico_ecs/systems/MovementSystem.h" @@ -12,7 +13,8 @@ namespace ecs::benchmarks::pico_ecs { class PicoEcsBenchmarkSuite final - : public ecs::benchmarks::base::ECSBenchmark<"pico_ecs", PicoEcsApplication, entities::EntityFactory> { + : public ecs::benchmarks::base::ECSBenchmark<"pico_ecs", PicoEcsApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { public: PicoEcsBenchmarkSuite() = default; diff --git a/img/ComplexSystemsUpdate.svg b/img/ComplexSystemsUpdate.svg index 2795145..424a000 100644 --- a/img/ComplexSystemsUpdate.svg +++ b/img/ComplexSystemsUpdate.svg @@ -1 +1 @@ -00.5M1M1.5M2M50.001250.01250.125125102510025FrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsComplexSystemsUpdateentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M50.001250.01250.125125102510025FrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsComplexSystemsUpdateentitiestime (ms) \ No newline at end of file diff --git a/img/ComplexSystemsUpdateMixedEntities.svg b/img/ComplexSystemsUpdateMixedEntities.svg index 2cf3c4c..3155966 100644 --- a/img/ComplexSystemsUpdateMixedEntities.svg +++ b/img/ComplexSystemsUpdateMixedEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M50.001250.01250.125125102510025FrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsComplexSystemsUpdateMixedEntitiesentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M50.001250.01250.125125102510025FrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsComplexSystemsUpdateMixedEntitiesentitiestime (ms) \ No newline at end of file diff --git a/img/ComplexSystemsUpdateNoEntities.svg b/img/ComplexSystemsUpdateNoEntities.svg index 2b49d4d..688636e 100644 --- a/img/ComplexSystemsUpdateNoEntities.svg +++ b/img/ComplexSystemsUpdateNoEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M910234567891002345FrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsComplexSystemsUpdateNoEntitiesentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M2345678910023456789FrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsComplexSystemsUpdateNoEntitiesentitiestime (ns) \ No newline at end of file diff --git a/img/CreateEmptyEntities.svg b/img/CreateEmptyEntities.svg index 15d7052..e3c0c62 100644 --- a/img/CreateEmptyEntities.svg +++ b/img/CreateEmptyEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M50.001250.01250.12512510251002FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsCreateEmptyEntitiesentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M50.001250.01250.12512510251002FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsCreateEmptyEntitiesentitiestime (ms) \ No newline at end of file diff --git a/img/CreateEmptyEntitiesInBulk.svg b/img/CreateEmptyEntitiesInBulk.svg index 96c92df..9719794 100644 --- a/img/CreateEmptyEntitiesInBulk.svg +++ b/img/CreateEmptyEntitiesInBulk.svg @@ -1 +1 @@ -00.5M1M1.5M2M0.001250.01250.125125102FrameworksEnTTCreateEmptyEntitiesInBulkentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M0.001250.01250.125125102FrameworksEnTTCreateEmptyEntitiesInBulkentitiestime (ms) \ No newline at end of file diff --git a/img/CreateEntities.svg b/img/CreateEntities.svg index 1a34c20..c76fa20 100644 --- a/img/CreateEntities.svg +++ b/img/CreateEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M0.001250.01250.1251251025100251000FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsCreateEntitiesentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M0.001250.01250.1251251025100251000FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsCreateEntitiesentitiestime (ms) \ No newline at end of file diff --git a/img/CreateEntitiesInBulk.svg b/img/CreateEntitiesInBulk.svg index 34822c5..eed2c24 100644 --- a/img/CreateEntitiesInBulk.svg +++ b/img/CreateEntitiesInBulk.svg @@ -1 +1 @@ -00.5M1M1.5M2M250.01250.1251251025100FrameworksEnTTCreateEntitiesInBulkentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M250.01250.1251251025100FrameworksEnTTCreateEntitiesInBulkentitiestime (ms) \ No newline at end of file diff --git a/img/CreateNoEntities.svg b/img/CreateNoEntities.svg index 3358887..1fb8c7b 100644 --- a/img/CreateNoEntities.svg +++ b/img/CreateNoEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M510002510k25100k25FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsCreateNoEntitiesentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M5125102510025FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsCreateNoEntitiesentitiestime (us) \ No newline at end of file diff --git a/img/DestroyEntities.svg b/img/DestroyEntities.svg index 29d0f45..830b7fc 100644 --- a/img/DestroyEntities.svg +++ b/img/DestroyEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M0.001250.01250.12512510251002FrameworksEntityXEnTTGinsengFlecspico_ecsDestroyEntitiesentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M0.001250.01250.12512510251002FrameworksEntityXEnTTGinsengFlecspico_ecsDestroyEntitiesentitiestime (ms) \ No newline at end of file diff --git a/img/DestroyEntitiesInBulk.svg b/img/DestroyEntitiesInBulk.svg index 433ce14..f4bdb19 100644 --- a/img/DestroyEntitiesInBulk.svg +++ b/img/DestroyEntitiesInBulk.svg @@ -1 +1 @@ -00.5M1M1.5M2M0.001250.01250.1251251025100FrameworksEnTTDestroyEntitiesInBulkentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M0.001250.01250.1251251025100FrameworksEnTTDestroyEntitiesInBulkentitiestime (ms) \ No newline at end of file diff --git a/img/IterateThreeComponentsWithMixedEntities.svg b/img/IterateThreeComponentsWithMixedEntities.svg index 9a0a982..53e7c20 100644 --- a/img/IterateThreeComponentsWithMixedEntities.svg +++ b/img/IterateThreeComponentsWithMixedEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M10100100010k100k1M10MFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)IterateThreeComponentsWithMixedEntitiesentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.010.1110100100010kFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)IterateThreeComponentsWithMixedEntitiesentitiestime (us) \ No newline at end of file diff --git a/img/IterateTwoComponents.svg b/img/IterateTwoComponents.svg index 13ba45e..4dffd16 100644 --- a/img/IterateTwoComponents.svg +++ b/img/IterateTwoComponents.svg @@ -1 +1 @@ -00.5M1M1.5M2M10100100010k100k1M10MFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)IterateTwoComponentsentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.010.1110100100010kFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)IterateTwoComponentsentitiestime (us) \ No newline at end of file diff --git a/img/RemoveAddComponent.svg b/img/RemoveAddComponent.svg index 15a3b50..ca43634 100644 --- a/img/RemoveAddComponent.svg +++ b/img/RemoveAddComponent.svg @@ -1 +1 @@ -00.5M1M1.5M2M100μ0.0010.010.11101001000FrameworksEntityXEnTTGinsengFlecspico_ecsRemoveAddComponententitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M100μ0.0010.010.11101001000FrameworksEntityXEnTTGinsengFlecspico_ecsRemoveAddComponententitiestime (ms) \ No newline at end of file diff --git a/img/SystemsUpdate.svg b/img/SystemsUpdate.svg index ed33bac..3a0ffbb 100644 --- a/img/SystemsUpdate.svg +++ b/img/SystemsUpdate.svg @@ -1 +1 @@ -00.5M1M1.5M2M50.001250.01250.12512510251002FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsSystemsUpdateentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M50.001250.01250.12512510251002FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsSystemsUpdateentitiestime (ms) \ No newline at end of file diff --git a/img/SystemsUpdateMixedEntities.svg b/img/SystemsUpdateMixedEntities.svg index 55168df..66c65e9 100644 --- a/img/SystemsUpdateMixedEntities.svg +++ b/img/SystemsUpdateMixedEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M50.001250.01250.12512510251002FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsSystemsUpdateMixedEntitiesentitiestime (ms) \ No newline at end of file +00.5M1M1.5M2M50.001250.01250.12512510251002FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsSystemsUpdateMixedEntitiesentitiestime (ms) \ No newline at end of file diff --git a/img/SystemsUpdateNoEntities.svg b/img/SystemsUpdateNoEntities.svg index e9c35c4..adc42c2 100644 --- a/img/SystemsUpdateNoEntities.svg +++ b/img/SystemsUpdateNoEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M789102345678910023456FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsSystemsUpdateNoEntitiesentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M78910234567891002345FrameworksEntityXEnTTGinsengmustacheFlecspico_ecsSystemsUpdateNoEntitiesentitiestime (ns) \ No newline at end of file diff --git a/img/UnpackNoComponent.svg b/img/UnpackNoComponent.svg index 74b160a..1c02358 100644 --- a/img/UnpackNoComponent.svg +++ b/img/UnpackNoComponent.svg @@ -1 +1 @@ -00.5M1M1.5M2M110100100010k100k1M10M100MFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackNoComponententitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.0010.010.1110100100010k100kFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackNoComponententitiestime (us) \ No newline at end of file diff --git a/img/UnpackOneComponent.svg b/img/UnpackOneComponent.svg index d728bc3..60521bb 100644 --- a/img/UnpackOneComponent.svg +++ b/img/UnpackOneComponent.svg @@ -1 +1 @@ -00.5M1M1.5M2M10100100010k100k1M10M100MFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackOneComponententitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.010.1110100100010k100kFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackOneComponententitiestime (us) \ No newline at end of file diff --git a/img/UnpackOneComponentNoEntities.svg b/img/UnpackOneComponentNoEntities.svg index 141f712..ecfce11 100644 --- a/img/UnpackOneComponentNoEntities.svg +++ b/img/UnpackOneComponentNoEntities.svg @@ -1 +1 @@ -00.5M1M1.5M2M0.12512510251002510002510kFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackOneComponentNoEntitiesentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.12512510251002510002510kFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackOneComponentNoEntitiesentitiestime (ns) \ No newline at end of file diff --git a/img/UnpackThreeComponents.svg b/img/UnpackThreeComponents.svg index 9fab2a7..cec04f8 100644 --- a/img/UnpackThreeComponents.svg +++ b/img/UnpackThreeComponents.svg @@ -1 +1 @@ -00.5M1M1.5M2M10100100010k100k1M10M100MFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackThreeComponentsentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.010.1110100100010k100kFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackThreeComponentsentitiestime (us) \ No newline at end of file diff --git a/img/UnpackTwoComponents.svg b/img/UnpackTwoComponents.svg index a299464..f311afa 100644 --- a/img/UnpackTwoComponents.svg +++ b/img/UnpackTwoComponents.svg @@ -1 +1 @@ -00.5M1M1.5M2M10100100010k100k1M10M100MFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackTwoComponentsentitiestime (ns) \ No newline at end of file +00.5M1M1.5M2M0.010.1110100100010k100kFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsUnpackTwoComponentsentitiestime (us) \ No newline at end of file diff --git a/plot.config.json b/plot.config.json index 3928c3b..d9f38f2 100644 --- a/plot.config.json +++ b/plot.config.json @@ -1,20 +1,20 @@ { "data": { "ComplexSystemsUpdateMixedEntities": { - "index": "Update {:>5s} entities with 3 Systems", - "title": "Update systems (3 systems, mixed components)", + "index": "Update {:>5s} entities with 5 Systems", + "title": "Update systems (5 systems, mixed components)", "regex": "^BM_(.*_)?ComplexSystemsUpdateMixedEntities\\/[0-9]+$", - "header": "Update systems (for-each entities (with mixed components) in 3 systems)" + "header": "Update systems (for-each entities (with mixed components) in 5 systems)" }, "ComplexSystemsUpdateNoEntities": { - "index": "Update 0 entities with 3 systems", - "title": "Update Systems (3 Systems) with zero entities", + "index": "Update 0 entities with 5 systems", + "title": "Update Systems (5 Systems) with zero entities", "regex": "^BM_(.*_)?ComplexSystemsUpdate_NoEntities$", "header": "Update systems (for-each entities in 3 systems) with zero entities" }, "ComplexSystemsUpdate": { - "index": "Update {:>5s} entities with 3 systems", - "title": "Update Systems (3 Systems)", + "index": "Update {:>5s} entities with 5 systems", + "title": "Update Systems (5 Systems)", "regex": "^BM_(.*_)?ComplexSystemsUpdate\\/[0-9]+$", "header": "Update systems (for-each entities in 3 systems)" }, diff --git a/scripts/gen-benchmark-report/__main__.py b/scripts/gen-benchmark-report/__main__.py index 93ca203..10c546b 100644 --- a/scripts/gen-benchmark-report/__main__.py +++ b/scripts/gen-benchmark-report/__main__.py @@ -106,6 +106,7 @@ def gen_results(config, output_dir, reports): name = benchmark['name'] time = benchmark['real_time'] time_ns = None + time_us = None time_ms = None time_s = None time_min = None @@ -115,14 +116,22 @@ def gen_results(config, output_dir, reports): components_three = None key = '' unit = benchmark['time_unit'] - if benchmark['time_unit'] == 'ns': + if unit == 'ns': time_ns = int(time) - time_ms = time_ns / 1000000.0 + time_us = time_ns / 1000.0 + time_ms = time_us / 1000.0 time_s = time_ms / 1000.0 time_min = time_s / 60.0 - elif benchmark['time_unit'] == 'ms': - time_ns = int(time * 1000000.0) + elif unit == 'ms': time_ms = time + time_ns = time_ms * 1000000.0 + time_us = time_ns / 1000.0 + time_s = time_ms / 1000.0 + time_min = time_s / 60.0 + elif unit == 'us': + time_us = time + time_ns = time_us * 1000.0 + time_ms = time_ns / 1000000.0 time_s = time_ms / 1000.0 time_min = time_s / 60.0 @@ -148,7 +157,7 @@ def gen_results(config, output_dir, reports): if key not in entries_data: entries_data[key] = [] entries_data[key].append( - {'name': name, 'unit': unit, 'time': time, 'time_ns': time_ns, 'time_ms': time_ms, 'time_s': time_s, + {'name': name, 'unit': unit, 'time': time, 'time_ns': time_ns, 'time_us': time_us, 'time_ms': time_ms, 'time_s': time_s, 'time_min': time_min, 'entities': entities, 'components_one': components_one, 'components_two': components_two, 'components_three': components_three, @@ -195,6 +204,10 @@ def gen_results(config, output_dir, reports): if units[ek] != 's' and units[ek] != 'min': units[ek] = 'ms' break + elif ed['time_ns'] >= 1000.0: + if units[ek] != 's' and units[ek] != 'min' and units[ek] != 'ms': + units[ek] = 'us' + break for framework, result in results.items(): if '_meta' != framework: @@ -209,6 +222,8 @@ def gen_results(config, output_dir, reports): if ed['entities'] == e: if unit == 'ns': y.append(ed['time_ns']) + elif unit == 'us': + y.append(ed['time_us']) elif unit == 'ms': y.append(ed['time_ms']) elif unit == 's': @@ -235,6 +250,8 @@ def gen_results(config, output_dir, reports): if ed['entities'] == e: if unit == 'ns': y.append(ed['time_ns']) + elif unit == 'us': + y.append(ed['time_us']) elif unit == 'ms': y.append(ed['time_ms']) elif unit == 's': @@ -386,7 +403,7 @@ def gen_results_md(config, output_dir, results_filename, results, img_dir): find = False for ed in entries_data: if ed['entities'] == key: - small_summary_df_data[name].append("{:>8d}ns".format(int(ed['time_ns']))) + small_summary_df_data[name].append("{:>6d}us".format(int(ed['time_us']))) find = True break if not find: @@ -407,7 +424,7 @@ def gen_results_md(config, output_dir, results_filename, results, img_dir): find = False for ed in entries_data: if ed['entities'] == key: - small_df_data[ek][name].append("{:>6d}ns".format(int(ed['time_ns']))) + small_df_data[ek][name].append("{:>6d}us".format(int(ed['time_us']))) find = True break if not find: diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 34a7a9d..e1758c5 100755 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -3,13 +3,16 @@ add_library( ecs-benchmark-base INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/base/components/DataComponent.h + ${CMAKE_CURRENT_SOURCE_DIR}/base/components/HeroMonsterComponents.h ${CMAKE_CURRENT_SOURCE_DIR}/base/components/VelocityComponent.h ${CMAKE_CURRENT_SOURCE_DIR}/base/components/PositionComponent.h ${CMAKE_CURRENT_SOURCE_DIR}/base/systems/DataSystem.h + ${CMAKE_CURRENT_SOURCE_DIR}/base/systems/HeroMonsterSystems.h ${CMAKE_CURRENT_SOURCE_DIR}/base/systems/MoreComplexSystem.h ${CMAKE_CURRENT_SOURCE_DIR}/base/systems/MovementSystem.h ${CMAKE_CURRENT_SOURCE_DIR}/base/systems/System.h ${CMAKE_CURRENT_SOURCE_DIR}/base/Application.h + ${CMAKE_CURRENT_SOURCE_DIR}/base/random.h ${CMAKE_CURRENT_SOURCE_DIR}/base/entities/EntityFactory.h) add_library(ecs-benchmark::base ALIAS ecs-benchmark-base) diff --git a/src/base/base/Application.h b/src/base/base/Application.h index b454373..051bd6b 100644 --- a/src/base/base/Application.h +++ b/src/base/base/Application.h @@ -7,7 +7,8 @@ namespace ecs::benchmarks::base { -template +template class Application { public: using EntityManager = tEntityManager; @@ -44,11 +45,22 @@ class Application { return std::make_unique(); } + std::unique_ptr> + createHealthSystem(EntityManager& /*entities*/) { + return std::make_unique(); + } + std::unique_ptr> + createDamageSystem(EntityManager& /*entities*/) { + return std::make_unique(); + } + virtual void init() { m_systems.emplace_back(createMovementSystem(m_entities)); m_systems.emplace_back(createDataSystem(m_entities)); if (m_add_more_complex_system) { m_systems.emplace_back(createMoreComplexSystem(m_entities)); + m_systems.emplace_back(createHealthSystem(m_entities)); + m_systems.emplace_back(createDamageSystem(m_entities)); } for (auto& system : m_systems) { diff --git a/src/base/base/components/HeroMonsterComponents.h b/src/base/base/components/HeroMonsterComponents.h new file mode 100644 index 0000000..65298cb --- /dev/null +++ b/src/base/base/components/HeroMonsterComponents.h @@ -0,0 +1,29 @@ +#ifndef ECS_BENCHMARKS_BASE_COMPONENTS_HEROMONSTERCOMPONENT_H_ +#define ECS_BENCHMARKS_BASE_COMPONENTS_HEROMONSTERCOMPONENT_H_ + +#include "base/random.h" + +namespace ecs::benchmarks::base::components { + +enum class PlayerType { NPC, Monster, Hero }; + +struct PlayerComponent { + ecs::benchmarks::base::random_xoshiro128 rng{}; + PlayerType type{PlayerType::NPC}; +}; + +enum class StatusEffect { Spawn, Dead, Alive }; +struct HealthComponent { + int32_t hp{0}; + int32_t maxhp{0}; + StatusEffect status{StatusEffect::Spawn}; +}; + +struct DamageComponent { + int32_t atk{0}; + int32_t def{0}; +}; + +} // namespace ecs::benchmarks::base::components + +#endif \ No newline at end of file diff --git a/src/base/base/components/PositionComponent.h b/src/base/base/components/PositionComponent.h index 8c09845..e46d139 100644 --- a/src/base/base/components/PositionComponent.h +++ b/src/base/base/components/PositionComponent.h @@ -4,8 +4,8 @@ namespace ecs::benchmarks::base::components { struct PositionComponent { - float x{0.0F}; - float y{0.0F}; + double x{0.0F}; + double y{0.0F}; }; diff --git a/src/base/base/components/VelocityComponent.h b/src/base/base/components/VelocityComponent.h index 82fa42c..d430bd9 100644 --- a/src/base/base/components/VelocityComponent.h +++ b/src/base/base/components/VelocityComponent.h @@ -4,8 +4,8 @@ namespace ecs::benchmarks::base::components { struct VelocityComponent { - float x{1.0F}; - float y{1.0F}; + double x{1.0}; + double y{1.0}; }; } // namespace ecs::benchmarks::base::components diff --git a/src/base/base/entities/HeroMonsterEntityFactory.h b/src/base/base/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..01cec1c --- /dev/null +++ b/src/base/base/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,86 @@ +#ifndef ECS_BENCHMARKS_BASE_HERMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_BASE_HERMONSTERENTITYFACTORY_H_ + +#include +#include +#include + +namespace ecs::benchmarks::base::entities { + +template +class HeroMonsterEntityFactory { +public: + using EntityManager = tEntityManager; + using Entity = tEntity; + using PlayerComponent = tPlayerComponent; + using HealthComponent = tHealthComponent; + using DamageComponent = tDamageComponent; + + struct PlayerArchetype { + PlayerComponent player_comp; + HealthComponent health_comp; + DamageComponent damage_comp; + }; + struct MonsterArchetype { + PlayerComponent player_comp; + HealthComponent health_comp; + DamageComponent damage_comp; + }; + + // virtual dtor and the rule of 6 + HeroMonsterEntityFactory() = default; + virtual ~HeroMonsterEntityFactory() = default; + HeroMonsterEntityFactory(const HeroMonsterEntityFactory&) = default; + HeroMonsterEntityFactory& operator=(const HeroMonsterEntityFactory&) = default; + HeroMonsterEntityFactory(HeroMonsterEntityFactory&&) noexcept = default; + HeroMonsterEntityFactory& operator=(HeroMonsterEntityFactory&&) noexcept = default; + + virtual Entity createRandom(EntityManager& registry) = 0; + virtual Entity createHero(EntityManager& registry) = 0; + virtual Entity createMonster(EntityManager& registry) = 0; + + virtual PlayerComponent& getPlayerComponent(EntityManager& registry, Entity entity) = 0; + virtual HealthComponent& getHealthComponent(EntityManager& registry, Entity entity) = 0; + virtual DamageComponent& getDamageComponent(EntityManager& registry, Entity entity) = 0; + + virtual void addComponents(EntityManager& registry, Entity entity) = 0; + + ecs::benchmarks::base::components::PlayerType + initComponents(EntityManager& registry, Entity entity, + std::optional opt_player_type = std::nullopt) { + using namespace ecs::benchmarks::base::components; + auto& player = getPlayerComponent(registry, entity); + auto& health = getHealthComponent(registry, entity); + auto& damage = getDamageComponent(registry, entity); + + player.type = opt_player_type.value_or([&player]() { + const auto player_type_rate = player.rng.range(1, 100); + return (player_type_rate <= 3) ? PlayerType::NPC + : (player_type_rate <= 30) ? PlayerType::Hero + : PlayerType::Monster; + }()); + switch (player.type) { + case PlayerType::Hero: + health.maxhp = gsl::narrow_cast(player.rng.range(5, 15)); + damage.def = gsl::narrow_cast(player.rng.range(2, 6)); + damage.atk = gsl::narrow_cast(player.rng.range(4, 10)); + break; + case PlayerType::Monster: + health.maxhp = gsl::narrow_cast(player.rng.range(4, 12)); + damage.def = gsl::narrow_cast(player.rng.range(2, 8)); + damage.atk = gsl::narrow_cast(player.rng.range(3, 9)); + break; + case PlayerType::NPC: + health.maxhp = gsl::narrow_cast(player.rng.range(6, 12)); + damage.def = gsl::narrow_cast(player.rng.range(3, 8)); + damage.atk = 0; + break; + } + return player.type; + } +}; + +} // namespace ecs::benchmarks::base::entities + +#endif \ No newline at end of file diff --git a/src/base/base/random.h b/src/base/base/random.h new file mode 100644 index 0000000..f09606a --- /dev/null +++ b/src/base/base/random.h @@ -0,0 +1,204 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ECS_BENCHMARKS_BASE_RANDOM_H_ +#define ECS_BENCHMARKS_BASE_RANDOM_H_ + +#include +#include +#include +#include +#include + +namespace ecs::benchmarks::base { + +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + +To the extent possible under law, the author has dedicated all copyright +and related and neighboring rights to this software to the public domain +worldwide. This software is distributed without any warranty. + +See . */ +class random_xoshiro128 { +public: + //*************************************************************************** + /// Default constructor. + /// Attempts to come up with a unique non-zero seed. + //*************************************************************************** + random_xoshiro128() noexcept { + // An attempt to come up with a unique non-zero seed, + // based on the address of the instance. + const auto n = std::bit_cast(this); + const auto seed = static_cast(n); + initialise(seed); + } + + //*************************************************************************** + /// Constructor with seed value. + ///\param seed The new seed value. + //*************************************************************************** + constexpr explicit random_xoshiro128(uint32_t seed) noexcept { initialise(seed); } + + //*************************************************************************** + /// Initialises the sequence with a new seed value. + ///\param seed The new seed value. + //*************************************************************************** + constexpr void initialise(uint32_t seed) noexcept { + // Add the first four primes to ensure that the seed isn't zero. + state[0] = seed + 3; + state[1] = seed + 5; + state[2] = seed + 7; + state[3] = seed + 11; + } + + constexpr explicit random_xoshiro128(const std::array& s) : state(s) {} + + //*************************************************************************** + /// Get the next random_xoshiro128 number. + //*************************************************************************** + constexpr uint32_t operator()() noexcept { return next(); } + + //*************************************************************************** + /// Get the next random_xoshiro128 number in a specified inclusive range. + //*************************************************************************** + constexpr uint32_t range(uint32_t low, uint32_t high) noexcept { + const uint32_t r = high - low + 1; + return (operator()() % r) + low; + } + + constexpr inline uint32_t range_max() noexcept { + return range(std::numeric_limits::min(), std::numeric_limits::max()); + } + + constexpr inline uint32_t range_min(uint32_t min) noexcept { + return range(min, std::numeric_limits::max()); + } + +public: + std::array state; + +private: + /* This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid + generators. It has excellent speed, a state size (128 bits) that is + large enough for mild parallelism, and it passes all tests we are aware + of. + + Note that version 1.0 had mistakenly s[0] instead of s[1] as state + word passed to the scrambler. + + For generating just single-precision (i.e., 32-bit) floating-point + numbers, xoshiro128+ is even faster. + + The state must be seeded so that it is not everywhere zero. */ + + static inline constexpr uint32_t rotl(const uint32_t x, int k) noexcept { return (x << k) | (x >> (32 - k)); } + + constexpr uint32_t next() noexcept { + const uint32_t result = rotl(state[1] * 5, 7) * 9; + + const uint32_t t = state[1] << 9; + + state[2] ^= state[0]; + state[3] ^= state[1]; + state[1] ^= state[2]; + state[0] ^= state[3]; + + state[2] ^= t; + + state[3] = rotl(state[3], 11); + + return result; + } + + + /* This is the jump function for the generator. It is equivalent + to 2^64 calls to next(); it can be used to generate 2^64 + non-overlapping subsequences for parallel computations. */ + /* + constexpr void jump() noexcept { + constexpr uint32_t JUMP[] = {0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b}; + + uint32_t s0 = 0; + uint32_t s1 = 0; + uint32_t s2 = 0; + uint32_t s3 = 0; + for (size_t i = 0; i < sizeof JUMP / sizeof *JUMP; i++) { + for (size_t b = 0; b < 32; b++) { + if (JUMP[i] & UINT32_C(1) << b) { + s0 ^= state[0]; + s1 ^= state[1]; + s2 ^= state[2]; + s3 ^= state[3]; + } + next(); + } + } + + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; + } + */ + + + /* This is the long-jump function for the generator. It is equivalent to + 2^96 calls to next(); it can be used to generate 2^32 starting points, + from each of which jump() will generate 2^32 non-overlapping + subsequences for parallel distributed computations. */ + /* + constexpr void long_jump() noexcept { + constexpr uint32_t LONG_JUMP[] = {0xb523952e, 0x0b6f099f, 0xccf5a0ef, 0x1c580662}; + + uint32_t s0 = 0; + uint32_t s1 = 0; + uint32_t s2 = 0; + uint32_t s3 = 0; + for (size_t i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) { + for (size_t b = 0; b < 32; b++) { + if (LONG_JUMP[i] & UINT32_C(1) << b) { + s0 ^= state[0]; + s1 ^= state[1]; + s2 ^= state[2]; + s3 ^= state[3]; + } + next(); + } + } + + state[0] = s0; + state[1] = s1; + state[2] = s2; + state[3] = s3; + } + */ +}; + +} // namespace ecs::benchmarks::base + +#endif \ No newline at end of file diff --git a/src/base/base/systems/HeroMonsterSystems.h b/src/base/base/systems/HeroMonsterSystems.h new file mode 100644 index 0000000..482545c --- /dev/null +++ b/src/base/base/systems/HeroMonsterSystems.h @@ -0,0 +1,61 @@ +#ifndef ECS_BENCHMARKS_BASE_HEROMONSTERSYSTEMS_H_ +#define ECS_BENCHMARKS_BASE_HEROMONSTERSYSTEMS_H_ + +#include "System.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::base::systems { + +template +class HealthSystem : public System { +public: + // virtual dtor and the rule of 6 + HealthSystem() = default; + virtual ~HealthSystem() = default; + HealthSystem(const HealthSystem&) = delete; + HealthSystem& operator=(const HealthSystem&) = delete; + HealthSystem(HealthSystem&&) noexcept = default; + HealthSystem& operator=(HealthSystem&&) noexcept = default; + + static void updateHealth(ecs::benchmarks::base::components::HealthComponent& health) { + using namespace ecs::benchmarks::base::components; + if (health.hp <= 0) { + health.hp = 0; + health.status = StatusEffect::Dead; + } else if (health.hp > health.maxhp) { + health.hp = health.maxhp; + } else if (health.status == StatusEffect::Dead && health.hp == 0) { + health.hp = health.maxhp; + health.status = StatusEffect::Spawn; + } else { + health.status = StatusEffect::Alive; + } + } +}; + +template +class DamageSystem : public System { +public: + // virtual dtor and the rule of 6 + DamageSystem() = default; + virtual ~DamageSystem() = default; + DamageSystem(const DamageSystem&) = delete; + DamageSystem& operator=(const DamageSystem&) = delete; + DamageSystem(DamageSystem&&) noexcept = default; + DamageSystem& operator=(DamageSystem&&) noexcept = default; + + static void updateDamage(ecs::benchmarks::base::components::HealthComponent& health, + const ecs::benchmarks::base::components::DamageComponent& damage) { + using namespace ecs::benchmarks::base::components; + // Calculate damage + const int totalDamage = damage.atk - damage.def; + + if (totalDamage > 0) { + health.hp -= totalDamage; + } + } +}; + +} // namespace ecs::benchmarks::base::systems + +#endif \ No newline at end of file diff --git a/src/base/base/systems/MovementSystem.h b/src/base/base/systems/MovementSystem.h index d781707..2f966b1 100644 --- a/src/base/base/systems/MovementSystem.h +++ b/src/base/base/systems/MovementSystem.h @@ -24,7 +24,7 @@ class MovementSystem : public System { MovementSystem& operator=(MovementSystem&&) noexcept = default; static void updatePosition(ecs::benchmarks::base::components::PositionComponent& position, - const ecs::benchmarks::base::components::VelocityComponent& direction, TimeDelta dt) { + const ecs::benchmarks::base::components::VelocityComponent& direction, double dt) { position.x += direction.x * dt; position.y += direction.y * dt; } diff --git a/src/entityx/CMakeLists.txt b/src/entityx/CMakeLists.txt index b36f885..e303521 100755 --- a/src/entityx/CMakeLists.txt +++ b/src/entityx/CMakeLists.txt @@ -31,6 +31,8 @@ add_library( entityx/systems/MovementSystem.cpp entityx/entities/EntityFactory.h entityx/entities/EntityFactory.cpp + entityx/entities/HeroMonsterEntityFactory.h + entityx/entities/HeroMonsterEntityFactory.cpp entityx/EntityXApplication.h entityx/EntityXApplication.cpp) add_library(ecs-benchmark::example::entityx ALIAS ecs-benchmark-example-entityx) diff --git a/src/entityx/entityx/EntityXApplication.cpp b/src/entityx/entityx/EntityXApplication.cpp index 6aa3e56..4e8d8b6 100644 --- a/src/entityx/entityx/EntityXApplication.cpp +++ b/src/entityx/entityx/EntityXApplication.cpp @@ -18,6 +18,8 @@ void EntityXApplication::update(TimeDelta dt) { systems.update(dt); if (m_add_more_complex_system) { systems.update(dt); + systems.update(dt); + systems.update(dt); } } } // namespace ecs::benchmarks::entityx \ No newline at end of file diff --git a/src/entityx/entityx/entities/EntityFactory.h b/src/entityx/entityx/entities/EntityFactory.h index 545f55e..b7bedb2 100644 --- a/src/entityx/entityx/entities/EntityFactory.h +++ b/src/entityx/entityx/entities/EntityFactory.h @@ -24,20 +24,24 @@ class EntityFactory { static void clear(EntityManager& registry); - [[nodiscard]] static inline auto getComponentOneConst(EntityManager& entities, Entity entity) { - return entities.component(entity.id()); + [[nodiscard]] static inline const ecs::benchmarks::base::components::PositionComponent& + getComponentOneConst(EntityManager& entities, Entity entity) { + return *entities.component(entity.id()); } - [[nodiscard]] static inline auto getComponentTwoConst(EntityManager& entities, Entity entity) { - return entities.component(entity.id()); + [[nodiscard]] static inline const ecs::benchmarks::base::components::VelocityComponent& + getComponentTwoConst(EntityManager& entities, Entity entity) { + return *entities.component(entity.id()); } - [[nodiscard]] static inline auto getComponentOne(EntityManager& entities, Entity entity) { - return entities.component(entity.id()); + [[nodiscard]] static inline ecs::benchmarks::base::components::PositionComponent& + getComponentOne(EntityManager& entities, Entity entity) { + return *entities.component(entity.id()); } - [[nodiscard]] static inline auto getComponentTwo(EntityManager& entities, Entity entity) { - return entities.component(entity.id()); + [[nodiscard]] static inline ecs::benchmarks::base::components::VelocityComponent& + getComponentTwo(EntityManager& entities, Entity entity) { + return *entities.component(entity.id()); } [[nodiscard]] static inline auto getOptionalComponentThree(EntityManager& entities, Entity entity) { diff --git a/src/entityx/entityx/entities/HeroMonsterEntityFactory.cpp b/src/entityx/entityx/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..261cea8 --- /dev/null +++ b/src/entityx/entityx/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,40 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::entityx::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + ret.assign(); + ret.assign(); + ret.assign(); + initComponents(entities, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + ret.assign(); + ret.assign(); + ret.assign(); + initComponents(entities, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + ret.assign(); + ret.assign(); + ret.assign(); + initComponents(entities, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& /*entities*/, Entity entity) { + entity.assign(); + entity.assign(); + entity.assign(); +} + +} // namespace ecs::benchmarks::entityx::entities diff --git a/src/entityx/entityx/entities/HeroMonsterEntityFactory.h b/src/entityx/entityx/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..e0f1098 --- /dev/null +++ b/src/entityx/entityx/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,42 @@ +#ifndef ECS_BENCHMARKS_ENTITYX_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_ENTITYX_HEROMONSTERENTITYFACTORY_H_ + +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::entityx::entities { + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::entityx::EntityManager, ::entityx::Entity, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + // using EntityManager = ::entityx::registry; + // using Entity = ::entityx::Entity; + + Entity createRandom(EntityManager& registry) override; + Entity createHero(EntityManager& registry) override; + Entity createMonster(EntityManager& registry) override; + + void addComponents(EntityManager& registry, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& getPlayerComponent(EntityManager& entities, + Entity entity) override { + return *entities.component(entity.id()); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& getHealthComponent(EntityManager& entities, + Entity entity) override { + return *entities.component(entity.id()); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& getDamageComponent(EntityManager& entities, + Entity entity) override { + return *entities.component(entity.id()); + } +}; + +} // namespace ecs::benchmarks::entityx::entities + +#endif \ No newline at end of file diff --git a/src/entityx/entityx/systems/MoreComplexSystem.cpp b/src/entityx/entityx/systems/MoreComplexSystem.cpp index 325111c..0229349 100644 --- a/src/entityx/entityx/systems/MoreComplexSystem.cpp +++ b/src/entityx/entityx/systems/MoreComplexSystem.cpp @@ -12,7 +12,6 @@ void MoreComplexSystem::update(EntityManager& entities, EventManager& /*events*/ updateComponents(position, direction, data); }); } - void MoreComplexSystem::update(EntityManager& entities, TimeDelta /*dt*/) { entities.each( @@ -21,4 +20,31 @@ void MoreComplexSystem::update(EntityManager& entities, TimeDelta /*dt*/) { }); } + +void HealthSystem::update(EntityManager& entities, EventManager& /*events*/, TimeDelta /*dt*/) { + entities.each([this](auto /*entity*/, auto& health) { + updateHealth(health); + }); +} +void HealthSystem::update(EntityManager& entities, TimeDelta /*dt*/) { + entities.each([this](auto /*entity*/, auto& health) { + updateHealth(health); + }); +} + +void DamageSystem::update(EntityManager& entities, EventManager& /*events*/, TimeDelta /*dt*/) { + entities.each( + [this](auto /*entity*/, auto& health, const auto& damage) { + updateDamage(health, damage); + }); +} +void DamageSystem::update(EntityManager& entities, TimeDelta /*dt*/) { + entities.each( + [this](auto /*entity*/, auto& health, const auto& damage) { + updateDamage(health, damage); + }); +} + } // namespace ecs::benchmarks::entityx::systems \ No newline at end of file diff --git a/src/entityx/entityx/systems/MoreComplexSystem.h b/src/entityx/entityx/systems/MoreComplexSystem.h index fd0029c..76b567e 100644 --- a/src/entityx/entityx/systems/MoreComplexSystem.h +++ b/src/entityx/entityx/systems/MoreComplexSystem.h @@ -1,6 +1,7 @@ #ifndef ECS_BENCHMARKS_ENTITYX_MORECOMPLEXSYSTEM_H_ #define ECS_BENCHMARKS_ENTITYX_MORECOMPLEXSYSTEM_H_ +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" #include @@ -16,6 +17,26 @@ class MoreComplexSystem final : public ::entityx::System, void update(EntityManager& entities, TimeDelta dt) override; }; +class HealthSystem final : public ::entityx::System, + ecs::benchmarks::base::systems::HealthSystem<::entityx::EntityManager, float> { +public: + using EventManager = ::entityx::EventManager; + + void update(EntityManager& entities, EventManager& events, TimeDelta dt) override; + + void update(EntityManager& entities, TimeDelta dt) override; +}; + +class DamageSystem final : public ::entityx::System, + ecs::benchmarks::base::systems::DamageSystem<::entityx::EntityManager, float> { +public: + using EventManager = ::entityx::EventManager; + + void update(EntityManager& entities, EventManager& events, TimeDelta dt) override; + + void update(EntityManager& entities, TimeDelta dt) override; +}; + } // namespace ecs::benchmarks::entityx::systems #endif \ No newline at end of file diff --git a/src/entt/CMakeLists.txt b/src/entt/CMakeLists.txt index af63c94..b823fd8 100755 --- a/src/entt/CMakeLists.txt +++ b/src/entt/CMakeLists.txt @@ -40,6 +40,8 @@ add_library( entt/systems/GroupMovementSystem.cpp entt/entities/EntityFactory.h entt/entities/EntityFactory.cpp + entt/entities/HeroMonsterEntityFactory.h + entt/entities/HeroMonsterEntityFactory.cpp entt/entities/StableEntityFactory.h entt/entities/StableEntityFactory.cpp entt/EnttApplication.h diff --git a/src/entt/entt/EnttApplication.h b/src/entt/entt/EnttApplication.h index 39f65c2..50292e0 100644 --- a/src/entt/entt/EnttApplication.h +++ b/src/entt/entt/EnttApplication.h @@ -10,7 +10,8 @@ namespace ecs::benchmarks::entt { class EnttApplication final : public ecs::benchmarks::base::Application<::entt::registry, float, systems::MovementSystem, systems::DataSystem, - systems::MoreComplexSystem> { + systems::MoreComplexSystem, systems::HealthSystem, + systems::DamageSystem> { public: EnttApplication() = default; diff --git a/src/entt/entt/EnttGroupApplication.h b/src/entt/entt/EnttGroupApplication.h index 5206a16..614471f 100644 --- a/src/entt/entt/EnttGroupApplication.h +++ b/src/entt/entt/EnttGroupApplication.h @@ -8,11 +8,13 @@ #include "systems/DataSystem.h" #include "systems/GroupMoreComplexSystem.h" #include "systems/GroupMovementSystem.h" +#include "systems/MoreComplexSystem.h" namespace ecs::benchmarks::entt { class EnttGroupApplication final : public ecs::benchmarks::base::Application<::entt::registry, float, systems::GroupMovementSystem, - systems::DataSystem, systems::GroupMoreComplexSystem> { + systems::DataSystem, systems::MoreComplexSystem, + systems::GroupHealthSystem, systems::GroupDamageSystem> { public: EnttGroupApplication() = default; diff --git a/src/entt/entt/EnttRuntimeApplication.h b/src/entt/entt/EnttRuntimeApplication.h index 2455cdf..f979f41 100644 --- a/src/entt/entt/EnttRuntimeApplication.h +++ b/src/entt/entt/EnttRuntimeApplication.h @@ -12,7 +12,8 @@ namespace ecs::benchmarks::entt { class EnttRuntimeApplication final : public ecs::benchmarks::base::Application<::entt::registry, float, systems::RuntimeMovementSystem, - systems::RuntimeDataSystem, systems::RuntimeMoreComplexSystem> { + systems::RuntimeDataSystem, systems::RuntimeMoreComplexSystem, + systems::RuntimeHealthSystem, systems::RuntimeDamageSystem> { public: EnttRuntimeApplication() = default; explicit EnttRuntimeApplication(bool add_more_complex_system) : Application(add_more_complex_system) {} diff --git a/src/entt/entt/StableEnttApplication.h b/src/entt/entt/StableEnttApplication.h index 5a05072..05abe86 100644 --- a/src/entt/entt/StableEnttApplication.h +++ b/src/entt/entt/StableEnttApplication.h @@ -11,7 +11,8 @@ namespace ecs::benchmarks::entt { class StableEnttApplication final : public ecs::benchmarks::base::Application<::entt::registry, float, systems::StableMovementSystem, - systems::DataSystem, systems::MoreComplexSystem> { + systems::DataSystem, systems::MoreComplexSystem, systems::HealthSystem, + systems::DamageSystem> { public: StableEnttApplication() = default; explicit StableEnttApplication(bool add_more_complex_system) : Application(add_more_complex_system) {} diff --git a/src/entt/entt/StableEnttRuntimeApplication.h b/src/entt/entt/StableEnttRuntimeApplication.h index d630ab0..2505010 100644 --- a/src/entt/entt/StableEnttRuntimeApplication.h +++ b/src/entt/entt/StableEnttRuntimeApplication.h @@ -11,7 +11,8 @@ namespace ecs::benchmarks::entt { class StableEnttRuntimeApplication final : public ecs::benchmarks::base::Application<::entt::registry, float, systems::StableRuntimeMovementSystem, - systems::RuntimeDataSystem, systems::RuntimeMoreComplexSystem> { + systems::RuntimeDataSystem, systems::RuntimeMoreComplexSystem, + systems::RuntimeHealthSystem, systems::RuntimeDamageSystem> { public: StableEnttRuntimeApplication() = default; explicit StableEnttRuntimeApplication(bool add_more_complex_system) : Application(add_more_complex_system) {} diff --git a/src/entt/entt/entities/HeroMonsterEntityFactory.cpp b/src/entt/entt/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..9096167 --- /dev/null +++ b/src/entt/entt/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,40 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::entt::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = registry.create(); + registry.emplace(ret); + registry.emplace(ret); + registry.emplace(ret); + initComponents(registry, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = registry.create(); + registry.emplace(ret); + registry.emplace(ret); + registry.emplace(ret); + initComponents(registry, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = registry.create(); + registry.emplace(ret); + registry.emplace(ret); + registry.emplace(ret); + initComponents(registry, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& registry, Entity entity) { + registry.emplace_or_replace(entity); + registry.emplace_or_replace(entity); + registry.emplace_or_replace(entity); +} + +} // namespace ecs::benchmarks::entt::entities diff --git a/src/entt/entt/entities/HeroMonsterEntityFactory.h b/src/entt/entt/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..0be2c8d --- /dev/null +++ b/src/entt/entt/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,43 @@ +#ifndef ECS_BENCHMARKS_ENTT_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_ENTT_HEROMONSTERENTITYFACTORY_H_ + +#include "entt/entt.h" + +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" + +namespace ecs::benchmarks::entt::entities { + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::entt::registry, ::entt::registry::entity_type, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + // using EntityManager = ::entt::registry; + // using Entity = ::entt::registry::entity_type; + + Entity createRandom(EntityManager& registry) override; + Entity createHero(EntityManager& registry) override; + Entity createMonster(EntityManager& registry) override; + + void addComponents(EntityManager& registry, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& getPlayerComponent(EntityManager& registry, + Entity entity) override { + return registry.get(entity); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& getHealthComponent(EntityManager& registry, + Entity entity) override { + return registry.get(entity); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& getDamageComponent(EntityManager& registry, + Entity entity) override { + return registry.get(entity); + } +}; + +} // namespace ecs::benchmarks::entt::entities + +#endif \ No newline at end of file diff --git a/src/entt/entt/systems/GroupMoreComplexSystem.cpp b/src/entt/entt/systems/GroupMoreComplexSystem.cpp index 4b3bf2e..b4089df 100644 --- a/src/entt/entt/systems/GroupMoreComplexSystem.cpp +++ b/src/entt/entt/systems/GroupMoreComplexSystem.cpp @@ -14,4 +14,18 @@ void GroupMoreComplexSystem::update(EntityManager& registry, TimeDelta /*dt*/) { }); } +void GroupHealthSystem::update(EntityManager& registry, TimeDelta /*dt*/) { + registry.group().each([this](auto& health) { + updateHealth(health); + }); +} + +void GroupDamageSystem::update(EntityManager& registry, TimeDelta /*dt*/) { + registry + .group( + ::entt::get) + .each([this](const auto& damage, auto& health) { + updateDamage(health, damage); + }); +} } // namespace ecs::benchmarks::entt::systems \ No newline at end of file diff --git a/src/entt/entt/systems/GroupMoreComplexSystem.h b/src/entt/entt/systems/GroupMoreComplexSystem.h index 3b82df1..fa21652 100644 --- a/src/entt/entt/systems/GroupMoreComplexSystem.h +++ b/src/entt/entt/systems/GroupMoreComplexSystem.h @@ -3,6 +3,7 @@ #include "entt/entt.h" +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" namespace ecs::benchmarks::entt::systems { @@ -12,6 +13,16 @@ class GroupMoreComplexSystem final : public ecs::benchmarks::base::systems::More void update(EntityManager& registry, TimeDelta dt) override; }; +class GroupHealthSystem final : public ecs::benchmarks::base::systems::HealthSystem<::entt::registry, float> { +public: + void update(EntityManager& registry, TimeDelta dt) override; +}; + +class GroupDamageSystem final : public ecs::benchmarks::base::systems::DamageSystem<::entt::registry, float> { +public: + void update(EntityManager& registry, TimeDelta dt) override; +}; + } // namespace ecs::benchmarks::entt::systems #endif \ No newline at end of file diff --git a/src/entt/entt/systems/MoreComplexSystem.cpp b/src/entt/entt/systems/MoreComplexSystem.cpp index c6c68d1..632af0c 100644 --- a/src/entt/entt/systems/MoreComplexSystem.cpp +++ b/src/entt/entt/systems/MoreComplexSystem.cpp @@ -1,5 +1,6 @@ #include "MoreComplexSystem.h" #include "base/components/DataComponent.h" +#include "base/components/HeroMonsterComponents.h" #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" @@ -14,4 +15,17 @@ void MoreComplexSystem::update(EntityManager& registry, TimeDelta dt) { }); } +void HealthSystem::update(EntityManager& registry, TimeDelta dt) { + registry.view().each([this, dt](auto& position) { + updateHealth(position); + }); +} +void DamageSystem::update(EntityManager& registry, TimeDelta dt) { + registry + .view() + .each([this, dt](auto& health, const auto& damage) { + updateDamage(health, damage); + }); +} } // namespace ecs::benchmarks::entt::systems \ No newline at end of file diff --git a/src/entt/entt/systems/MoreComplexSystem.h b/src/entt/entt/systems/MoreComplexSystem.h index f164a8f..4a96702 100644 --- a/src/entt/entt/systems/MoreComplexSystem.h +++ b/src/entt/entt/systems/MoreComplexSystem.h @@ -3,6 +3,7 @@ #include "entt/entt.h" +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" namespace ecs::benchmarks::entt::systems { @@ -12,6 +13,16 @@ class MoreComplexSystem final : public ecs::benchmarks::base::systems::MoreCompl void update(EntityManager& registry, TimeDelta dt) override; }; +class HealthSystem final : public ecs::benchmarks::base::systems::HealthSystem<::entt::registry, float> { +public: + void update(EntityManager& registry, TimeDelta dt) override; +}; + +class DamageSystem final : public ecs::benchmarks::base::systems::DamageSystem<::entt::registry, float> { +public: + void update(EntityManager& registry, TimeDelta dt) override; +}; + } // namespace ecs::benchmarks::entt::systems #endif \ No newline at end of file diff --git a/src/entt/entt/systems/RuntimeMoreComplexSystem.cpp b/src/entt/entt/systems/RuntimeMoreComplexSystem.cpp index 412ee58..1e5c78b 100644 --- a/src/entt/entt/systems/RuntimeMoreComplexSystem.cpp +++ b/src/entt/entt/systems/RuntimeMoreComplexSystem.cpp @@ -10,7 +10,6 @@ void RuntimeMoreComplexSystem::init(EntityManager& registry) { .iterate(registry.storage()) .iterate(registry.storage()); } - void RuntimeMoreComplexSystem::update(EntityManager& registry, TimeDelta dt) { m_view.each([this, ®istry, dt](auto entity) { auto& position = registry.get(entity); @@ -20,4 +19,26 @@ void RuntimeMoreComplexSystem::update(EntityManager& registry, TimeDelta dt) { }); } +void RuntimeHealthSystem::init(EntityManager& registry) { + m_view.iterate(registry.storage()); +} +void RuntimeHealthSystem::update(EntityManager& registry, TimeDelta dt) { + m_view.each([this, ®istry, dt](auto entity) { + auto& health = registry.get(entity); + updateHealth(health); + }); +} + +void RuntimeDamageSystem::init(EntityManager& registry) { + m_view.iterate(registry.storage()) + .iterate(registry.storage()); +} +void RuntimeDamageSystem::update(EntityManager& registry, TimeDelta dt) { + m_view.each([this, ®istry, dt](auto entity) { + auto& health = registry.get(entity); + const auto& damage = registry.get(entity); + updateDamage(health, damage); + }); +} + } // namespace ecs::benchmarks::entt::systems \ No newline at end of file diff --git a/src/entt/entt/systems/RuntimeMoreComplexSystem.h b/src/entt/entt/systems/RuntimeMoreComplexSystem.h index 7340e46..c1f424f 100644 --- a/src/entt/entt/systems/RuntimeMoreComplexSystem.h +++ b/src/entt/entt/systems/RuntimeMoreComplexSystem.h @@ -3,6 +3,7 @@ #include "entt/entt.h" +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" namespace ecs::benchmarks::entt::systems { @@ -18,6 +19,26 @@ class RuntimeMoreComplexSystem final ::entt::runtime_view m_view{}; }; +class RuntimeHealthSystem final : public ecs::benchmarks::base::systems::HealthSystem<::entt::registry, float> { +public: + void init(EntityManager& entities) override; + + void update(EntityManager& registry, TimeDelta dt) override; + +private: + ::entt::runtime_view m_view{}; +}; + +class RuntimeDamageSystem final : public ecs::benchmarks::base::systems::DamageSystem<::entt::registry, float> { +public: + void init(EntityManager& entities) override; + + void update(EntityManager& registry, TimeDelta dt) override; + +private: + ::entt::runtime_view m_view{}; +}; + } // namespace ecs::benchmarks::entt::systems #endif \ No newline at end of file diff --git a/src/flecs/CMakeLists.txt b/src/flecs/CMakeLists.txt index 64d3ac3..9878a16 100755 --- a/src/flecs/CMakeLists.txt +++ b/src/flecs/CMakeLists.txt @@ -24,6 +24,8 @@ add_library( flecs/systems/MovementSystem.cpp flecs/entities/EntityFactory.h flecs/entities/EntityFactory.cpp + flecs/entities/HeroMonsterEntityFactory.h + flecs/entities/HeroMonsterEntityFactory.cpp flecs/FlecsApplication.h flecs/FlecsApplication.cpp) add_library(ecs-benchmark::example::flecs ALIAS ecs-benchmark-example-flecs) diff --git a/src/flecs/flecs/FlecsApplication.h b/src/flecs/flecs/FlecsApplication.h index 945e6df..773dad4 100644 --- a/src/flecs/flecs/FlecsApplication.h +++ b/src/flecs/flecs/FlecsApplication.h @@ -44,6 +44,11 @@ class FlecsApplication { ecs::benchmarks::base::components::VelocityComponent, ecs::benchmarks::base::components::DataComponent>() .each(systems::MoreComplexSystem::update); + m_world.system().each(systems::HealthSystem::update); + m_world + .system() + .each(systems::DamageSystem::update); } } diff --git a/src/flecs/flecs/entities/HeroMonsterEntityFactory.cpp b/src/flecs/flecs/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..55eff16 --- /dev/null +++ b/src/flecs/flecs/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,40 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::flecs::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.entity() + .add() + .add() + .add(); + initComponents(entities, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.entity() + .add() + .add() + .add(); + initComponents(entities, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.entity() + .add() + .add() + .add(); + initComponents(entities, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& /*entities*/, Entity entity) { + entity.add(); + entity.add(); + entity.add(); +} + +} // namespace ecs::benchmarks::flecs::entities diff --git a/src/flecs/flecs/entities/HeroMonsterEntityFactory.h b/src/flecs/flecs/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..020920d --- /dev/null +++ b/src/flecs/flecs/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,39 @@ +#ifndef ECS_BENCHMARKS_FLECS_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_FLECS_HEROMONSTERENTITYFACTORY_H_ + +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" +#include "flecs/custom_flecs.h" + +namespace ecs::benchmarks::flecs::entities { + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::flecs::world, ::flecs::entity, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + Entity createRandom(EntityManager& registry) override; + Entity createHero(EntityManager& registry) override; + Entity createMonster(EntityManager& registry) override; + + void addComponents(EntityManager& registry, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponent(EntityManager& /*entities*/, Entity entity) override { + return *entity.get_mut(); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& + getHealthComponent(EntityManager& /*entities*/, Entity entity) override { + return *entity.get_mut(); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& + getDamageComponent(EntityManager& /*entities*/, Entity entity) override { + return *entity.get_mut(); + } +}; + +} // namespace ecs::benchmarks::flecs::entities + +#endif \ No newline at end of file diff --git a/src/flecs/flecs/systems/MoreComplexSystem.h b/src/flecs/flecs/systems/MoreComplexSystem.h index 35def9a..b0361ae 100644 --- a/src/flecs/flecs/systems/MoreComplexSystem.h +++ b/src/flecs/flecs/systems/MoreComplexSystem.h @@ -3,6 +3,7 @@ #include "flecs/custom_flecs.h" +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" namespace ecs::benchmarks::flecs::systems { @@ -38,6 +39,48 @@ class MoreComplexSystem { static std::mt19937 m_eng; }; + +class HealthSystem { +public: + using TimeDelta = float; + using Entity = ::flecs::entity; + + inline static const auto update = [](::flecs::iter& /*it*/, size_t /*index*/, + ecs::benchmarks::base::components::HealthComponent& health) { + using namespace ecs::benchmarks::base::components; + if (health.hp <= 0) { + health.hp = 0; + health.status = StatusEffect::Dead; + } else if (health.hp > health.maxhp) { + health.hp = health.maxhp; + } else if (health.status == StatusEffect::Dead && health.hp == 0) { + health.hp = health.maxhp; + health.status = StatusEffect::Spawn; + } else { + health.status = StatusEffect::Alive; + } + }; +}; + + +class DamageSystem { +public: + using TimeDelta = float; + using Entity = ::flecs::entity; + + inline static const auto update = [](::flecs::iter& /*it*/, size_t /*index*/, + ecs::benchmarks::base::components::HealthComponent& health, + const ecs::benchmarks::base::components::DamageComponent& damage) { + using namespace ecs::benchmarks::base::components; + // Calculate damage + const int totalDamage = damage.atk - damage.def; + + if (totalDamage > 0) { + health.hp -= totalDamage; + } + }; +}; + } // namespace ecs::benchmarks::flecs::systems #endif \ No newline at end of file diff --git a/src/flecs/flecs/systems/MovementSystem.h b/src/flecs/flecs/systems/MovementSystem.h index 03705bc..d6fbb77 100644 --- a/src/flecs/flecs/systems/MovementSystem.h +++ b/src/flecs/flecs/systems/MovementSystem.h @@ -2,6 +2,7 @@ #define ECS_BENCHMARKS_FLECS_MOVEMENTSYSTEM_H_ #include "flecs/custom_flecs.h" +#include #include "base/systems/MovementSystem.h" @@ -9,13 +10,13 @@ namespace ecs::benchmarks::flecs::systems { class MovementSystem { public: - using TimeDelta = float; + using TimeDelta = double; using Entity = ::flecs::entity; inline static const auto update = [](::flecs::iter& it, size_t /*index*/, ecs::benchmarks::base::components::PositionComponent& position, const ecs::benchmarks::base::components::VelocityComponent& direction) { - const TimeDelta dt = it.delta_time(); + const auto dt = gsl::narrow_cast(it.delta_time()); position.x += direction.x * dt; position.y += direction.y * dt; }; diff --git a/src/ginseng/CMakeLists.txt b/src/ginseng/CMakeLists.txt index 23d9607..b1d95a3 100755 --- a/src/ginseng/CMakeLists.txt +++ b/src/ginseng/CMakeLists.txt @@ -23,6 +23,8 @@ add_library( ginseng/systems/MovementSystem.cpp ginseng/entities/EntityFactory.h ginseng/entities/EntityFactory.cpp + ginseng/entities/HeroMonsterEntityFactory.h + ginseng/entities/HeroMonsterEntityFactory.cpp ginseng/GinsengApplication.h ginseng/GinsengApplication.cpp) add_library(ecs-benchmark::example::ginseng ALIAS ecs-benchmark-example-ginseng) diff --git a/src/ginseng/ginseng/GinsengApplication.h b/src/ginseng/ginseng/GinsengApplication.h index 9fb03b5..fdfd61b 100644 --- a/src/ginseng/ginseng/GinsengApplication.h +++ b/src/ginseng/ginseng/GinsengApplication.h @@ -10,7 +10,8 @@ namespace ecs::benchmarks::ginseng { class GinsengApplication final : public ecs::benchmarks::base::Application<::ginseng::database, float, systems::MovementSystem, - systems::DataSystem, systems::MoreComplexSystem> { + systems::DataSystem, systems::MoreComplexSystem, systems::HealthSystem, + systems::DamageSystem> { public: GinsengApplication() = default; diff --git a/src/ginseng/ginseng/entities/HeroMonsterEntityFactory.cpp b/src/ginseng/ginseng/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..1fdb7f4 --- /dev/null +++ b/src/ginseng/ginseng/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,40 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::ginseng::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = registry.create_entity(); + registry.add_component(ret, ecs::benchmarks::base::components::PlayerComponent{}); + registry.add_component(ret, ecs::benchmarks::base::components::HealthComponent{}); + registry.add_component(ret, ecs::benchmarks::base::components::DamageComponent{}); + initComponents(registry, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = registry.create_entity(); + registry.add_component(ret, ecs::benchmarks::base::components::PlayerComponent{}); + registry.add_component(ret, ecs::benchmarks::base::components::HealthComponent{}); + registry.add_component(ret, ecs::benchmarks::base::components::DamageComponent{}); + initComponents(registry, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = registry.create_entity(); + registry.add_component(ret, ecs::benchmarks::base::components::PlayerComponent{}); + registry.add_component(ret, ecs::benchmarks::base::components::HealthComponent{}); + registry.add_component(ret, ecs::benchmarks::base::components::DamageComponent{}); + initComponents(registry, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& registry, Entity entity) { + registry.add_component(entity, ecs::benchmarks::base::components::PlayerComponent{}); + registry.add_component(entity, ecs::benchmarks::base::components::HealthComponent{}); + registry.add_component(entity, ecs::benchmarks::base::components::DamageComponent{}); +} + +} // namespace ecs::benchmarks::ginseng::entities diff --git a/src/ginseng/ginseng/entities/HeroMonsterEntityFactory.h b/src/ginseng/ginseng/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..cf87c6b --- /dev/null +++ b/src/ginseng/ginseng/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,43 @@ +#ifndef ECS_BENCHMARKS_GINSENG_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_GINSENG_HEROMONSTERENTITYFACTORY_H_ + +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::ginseng::entities { + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::ginseng::database, ::ginseng::database::ent_id, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + // using EntityManager = ::ginseng::database; + // using Entity = ::ginseng::database::ent_id; + using Component = ::ginseng::database::com_id; + + Entity createRandom(EntityManager& registry) override; + Entity createHero(EntityManager& registry) override; + Entity createMonster(EntityManager& registry) override; + + void addComponents(EntityManager& registry, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& getPlayerComponent(EntityManager& registry, + Entity entity) override { + return registry.get_component(entity); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& getHealthComponent(EntityManager& registry, + Entity entity) override { + return registry.get_component(entity); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& getDamageComponent(EntityManager& registry, + Entity entity) override { + return registry.get_component(entity); + } +}; + +} // namespace ecs::benchmarks::ginseng::entities + +#endif \ No newline at end of file diff --git a/src/ginseng/ginseng/systems/MoreComplexSystem.cpp b/src/ginseng/ginseng/systems/MoreComplexSystem.cpp index efc7ca7..8d2849a 100644 --- a/src/ginseng/ginseng/systems/MoreComplexSystem.cpp +++ b/src/ginseng/ginseng/systems/MoreComplexSystem.cpp @@ -13,4 +13,17 @@ void MoreComplexSystem::update(EntityManager& registry, TimeDelta /*dt*/) { }); } +void HealthSystem::update(EntityManager& registry, TimeDelta /*dt*/) { + registry.visit([this](ecs::benchmarks::base::components::HealthComponent& health) { + updateHealth(health); + }); +} + +void DamageSystem::update(EntityManager& registry, TimeDelta /*dt*/) { + registry.visit([this](ecs::benchmarks::base::components::HealthComponent& health, + const ecs::benchmarks::base::components::DamageComponent& damage) { + updateDamage(health, damage); + }); +} + } // namespace ecs::benchmarks::ginseng::systems \ No newline at end of file diff --git a/src/ginseng/ginseng/systems/MoreComplexSystem.h b/src/ginseng/ginseng/systems/MoreComplexSystem.h index 78de9b7..f6f5920 100644 --- a/src/ginseng/ginseng/systems/MoreComplexSystem.h +++ b/src/ginseng/ginseng/systems/MoreComplexSystem.h @@ -1,6 +1,7 @@ #ifndef ECS_BENCHMARKS_GINSENG_MORECOMPLEXSYSTEM_H_ #define ECS_BENCHMARKS_GINSENG_MORECOMPLEXSYSTEM_H_ +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" #include @@ -11,6 +12,16 @@ class MoreComplexSystem final : public ecs::benchmarks::base::systems::MoreCompl void update(EntityManager& registry, TimeDelta dt) override; }; +class HealthSystem final : public ecs::benchmarks::base::systems::HealthSystem<::ginseng::database, float> { +public: + void update(EntityManager& registry, TimeDelta dt) override; +}; + +class DamageSystem final : public ecs::benchmarks::base::systems::DamageSystem<::ginseng::database, float> { +public: + void update(EntityManager& registry, TimeDelta dt) override; +}; + } // namespace ecs::benchmarks::ginseng::systems #endif \ No newline at end of file diff --git a/src/mustache/CMakeLists.txt b/src/mustache/CMakeLists.txt index b8726a9..411a419 100755 --- a/src/mustache/CMakeLists.txt +++ b/src/mustache/CMakeLists.txt @@ -28,6 +28,8 @@ add_library( mustache/systems/MovementSystem.cpp mustache/entities/EntityFactory.h mustache/entities/EntityFactory.cpp + mustache/entities/HeroMonsterEntityFactory.h + mustache/entities/HeroMonsterEntityFactory.cpp mustache/MustacheApplication.h mustache/MustacheApplication.cpp) add_library(ecs-benchmark::example::mustache ALIAS ecs-benchmark-example-mustache) diff --git a/src/mustache/mustache/MustacheApplication.h b/src/mustache/mustache/MustacheApplication.h index 8795bc7..7431465 100644 --- a/src/mustache/mustache/MustacheApplication.h +++ b/src/mustache/mustache/MustacheApplication.h @@ -37,6 +37,8 @@ class MustacheApplication { m_world.systems().addSystem(); if (m_add_more_complex_system) { m_world.systems().addSystem(); + m_world.systems().addSystem(); + m_world.systems().addSystem(); } m_world.init(); } @@ -49,6 +51,8 @@ class MustacheApplication { } m_world.systems().removeSystem(); m_world.systems().removeSystem(); + m_world.systems().removeSystem(); + m_world.systems().removeSystem(); */ } diff --git a/src/mustache/mustache/entities/HeroMonsterEntityFactory.cpp b/src/mustache/mustache/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..0e2e1ec --- /dev/null +++ b/src/mustache/mustache/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,37 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::mustache::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + initComponents(entities, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + initComponents(entities, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + initComponents(entities, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& entities, Entity entity) { + entities.assign(entity); + entities.assign(entity); + entities.assign(entity); +} + +} // namespace ecs::benchmarks::mustache::entities diff --git a/src/mustache/mustache/entities/HeroMonsterEntityFactory.h b/src/mustache/mustache/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..e33f8f6 --- /dev/null +++ b/src/mustache/mustache/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,47 @@ +#ifndef ECS_BENCHMARKS_MUSTACHE_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_MUSTACHE_HEROMONSTERENTITYFACTORY_H_ + +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" +/// @FIXME: uint32_t for found in "mustache/ecs/system.hpp" +#include +#include + +namespace ecs::benchmarks::mustache::entities { + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::mustache::EntityManager, ::mustache::Entity, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + Entity createRandom(EntityManager& registry) override; + Entity createHero(EntityManager& registry) override; + Entity createMonster(EntityManager& registry) override; + + void addComponents(EntityManager& registry, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& getPlayerComponent(EntityManager& registry, + Entity entity) override { + return *registry + .getComponent( + entity); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& getHealthComponent(EntityManager& registry, + Entity entity) override { + return *registry + .getComponent( + entity); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& getDamageComponent(EntityManager& registry, + Entity entity) override { + return *registry + .getComponent( + entity); + } +}; + +} // namespace ecs::benchmarks::mustache::entities + +#endif \ No newline at end of file diff --git a/src/mustache/mustache/systems/MoreComplexSystem.cpp b/src/mustache/mustache/systems/MoreComplexSystem.cpp index 35555a5..c3708d9 100644 --- a/src/mustache/mustache/systems/MoreComplexSystem.cpp +++ b/src/mustache/mustache/systems/MoreComplexSystem.cpp @@ -15,7 +15,6 @@ void MoreComplexSystem::update(::mustache::World& world, TimeDelta dt) { }, run_mode); } - void MoreComplexSystem::onUpdate(::mustache::World& world) { constexpr auto run_mode = ::mustache::JobRunMode::kCurrentThread; world.entities().forEach( @@ -27,4 +26,43 @@ void MoreComplexSystem::onUpdate(::mustache::World& world) { }, run_mode); } + +void HealthSystem::update(::mustache::World& world, TimeDelta dt) { + constexpr auto run_mode = ::mustache::JobRunMode::kCurrentThread; + world.entities().forEach( + [this, dt](Entity /*entity*/, ecs::benchmarks::base::components::HealthComponent& health) { + updateHealth(health); + }, + run_mode); +} +void HealthSystem::onUpdate(::mustache::World& world) { + constexpr auto run_mode = ::mustache::JobRunMode::kCurrentThread; + world.entities().forEach( + [this](Entity /*entity*/, ecs::benchmarks::base::components::HealthComponent& health) { + // constexpr float dt = 1.0F / 60.0F; + updateHealth(health); + }, + run_mode); +} + +void DamageSystem::update(::mustache::World& world, TimeDelta dt) { + constexpr auto run_mode = ::mustache::JobRunMode::kCurrentThread; + world.entities().forEach( + [this, dt](Entity /*entity*/, ecs::benchmarks::base::components::HealthComponent& health, + const ecs::benchmarks::base::components::DamageComponent& damage) { + updateDamage(health, damage); + }, + run_mode); +} +void DamageSystem::onUpdate(::mustache::World& world) { + constexpr auto run_mode = ::mustache::JobRunMode::kCurrentThread; + world.entities().forEach( + [this](Entity /*entity*/, ecs::benchmarks::base::components::HealthComponent& health, + const ecs::benchmarks::base::components::DamageComponent& damage) { + // constexpr float dt = 1.0F / 60.0F; + updateDamage(health, damage); + }, + run_mode); +} + } // namespace ecs::benchmarks::mustache::systems \ No newline at end of file diff --git a/src/mustache/mustache/systems/MoreComplexSystem.h b/src/mustache/mustache/systems/MoreComplexSystem.h index 5fc4e76..78f4aaf 100644 --- a/src/mustache/mustache/systems/MoreComplexSystem.h +++ b/src/mustache/mustache/systems/MoreComplexSystem.h @@ -1,6 +1,7 @@ #ifndef ECS_BENCHMARKS_MUSTACHE_MORECOMPLEXSYSTEM_H_ #define ECS_BENCHMARKS_MUSTACHE_MORECOMPLEXSYSTEM_H_ +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" /// @FIXME: uint32_t for found in "mustache/ecs/system.hpp" #include @@ -18,6 +19,26 @@ class MoreComplexSystem final : public ::mustache::System, void onUpdate(::mustache::World& world) override; }; + +class HealthSystem final : public ::mustache::System, + ecs::benchmarks::base::systems::HealthSystem<::mustache::World, float> { +public: + using Entity = ::mustache::Entity; + + void update(::mustache::World& world, TimeDelta dt) override; + + void onUpdate(::mustache::World& world) override; +}; + +class DamageSystem final : public ::mustache::System, + ecs::benchmarks::base::systems::DamageSystem<::mustache::World, float> { +public: + using Entity = ::mustache::Entity; + + void update(::mustache::World& world, TimeDelta dt) override; + + void onUpdate(::mustache::World& world) override; +}; } // namespace ecs::benchmarks::mustache::systems #endif \ No newline at end of file diff --git a/src/openecs/CMakeLists.txt b/src/openecs/CMakeLists.txt index 57669d6..384bb56 100755 --- a/src/openecs/CMakeLists.txt +++ b/src/openecs/CMakeLists.txt @@ -17,6 +17,8 @@ add_library( openecs/systems/MovementSystem.cpp openecs/entities/EntityFactory.h openecs/entities/EntityFactory.cpp + openecs/entities/HeroMonsterEntityFactory.h + openecs/entities/HeroMonsterEntityFactory.cpp openecs/OpenECSApplication.h openecs/OpenECSApplication.cpp) add_library(ecs-benchmark::example::openecs ALIAS ecs-benchmark-example-openecs) diff --git a/src/openecs/openecs/entities/HeroMonsterEntityFactory.cpp b/src/openecs/openecs/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..2343961 --- /dev/null +++ b/src/openecs/openecs/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,32 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::openecs::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + ; + initComponents(entities, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + initComponents(entities, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& entities) { + using namespace ecs::benchmarks::base::components; + auto ret = entities.create(); + initComponents(entities, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& /*entities*/, Entity entity) { + entity.add(); + entity.add(); + entity.add(); +} + +} // namespace ecs::benchmarks::openecs::entities diff --git a/src/openecs/openecs/entities/HeroMonsterEntityFactory.h b/src/openecs/openecs/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..7fd3659 --- /dev/null +++ b/src/openecs/openecs/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,67 @@ +#ifndef ECS_BENCHMARKS_OPENECS_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_OPENECS_HEROMONSTERENTITYFACTORY_H_ + +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::openecs::entities { + +struct PlayerEntity final : public ::ecs::EntityAlias { + PlayerEntity() { + add(); + add(); + add(); + } +}; +struct HeroEntity final : public ::ecs::EntityAlias { + HeroEntity() { + add(); + add(); + add(); + } +}; +struct MonsterEntity final : public ::ecs::EntityAlias { + MonsterEntity() { + add(); + add(); + add(); + } +}; + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::ecs::EntityManager, ::ecs::Entity, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + Entity createRandom(EntityManager& entities) override; + Entity createHero(EntityManager& entities) override; + Entity createMonster(EntityManager& entities) override; + + void addComponents(EntityManager& entities, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponent(EntityManager& /*entities*/, Entity entity) override { + return entity.get(); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& + getHealthComponent(EntityManager& /*entities*/, Entity entity) override { + return entity.get(); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& + getDamageComponent(EntityManager& /*entities*/, Entity entity) override { + return entity.get(); + } +}; + +} // namespace ecs::benchmarks::openecs::entities + +#endif \ No newline at end of file diff --git a/src/pico_ecs/CMakeLists.txt b/src/pico_ecs/CMakeLists.txt index 95a9ccb..53a93d6 100755 --- a/src/pico_ecs/CMakeLists.txt +++ b/src/pico_ecs/CMakeLists.txt @@ -11,6 +11,8 @@ add_library( pico_ecs/systems/MovementSystem.cpp pico_ecs/entities/EntityFactory.h pico_ecs/entities/EntityFactory.cpp + pico_ecs/entities/HeroMonsterEntityFactory.h + pico_ecs/entities/HeroMonsterEntityFactory.cpp pico_ecs/PicoEcsApplication.h pico_ecs/PicoEcsApplication.cpp pico_ecs/pico_ecs.cpp) diff --git a/src/pico_ecs/pico_ecs/PicoEcsApplication.h b/src/pico_ecs/pico_ecs/PicoEcsApplication.h index 85a4551..e712842 100644 --- a/src/pico_ecs/pico_ecs/PicoEcsApplication.h +++ b/src/pico_ecs/pico_ecs/PicoEcsApplication.h @@ -38,12 +38,18 @@ class PicoEcsApplication { m_movement_system.init(m_registry); m_data_system.init(m_registry); m_more_complex_system.init(m_registry); + m_health_system.init(m_registry); + m_damage_system.init(m_registry); ecs_enable_system(m_registry.ecs.get(), m_movement_system.id()); ecs_enable_system(m_registry.ecs.get(), m_data_system.id()); if (m_add_more_complex_system) { ecs_enable_system(m_registry.ecs.get(), m_more_complex_system.id()); + ecs_enable_system(m_registry.ecs.get(), m_health_system.id()); + ecs_enable_system(m_registry.ecs.get(), m_damage_system.id()); } else { ecs_disable_system(m_registry.ecs.get(), m_more_complex_system.id()); + ecs_disable_system(m_registry.ecs.get(), m_health_system.id()); + ecs_disable_system(m_registry.ecs.get(), m_damage_system.id()); } } @@ -59,6 +65,8 @@ class PicoEcsApplication { systems::MovementSystem m_movement_system; systems::DataSystem m_data_system; systems::MoreComplexSystem m_more_complex_system; + systems::HealthSystem m_health_system; + systems::DamageSystem m_damage_system; }; } // namespace ecs::benchmarks::pico_ecs diff --git a/src/pico_ecs/pico_ecs/entities/EntityFactory.h b/src/pico_ecs/pico_ecs/entities/EntityFactory.h index 7e7d129..3a910d3 100644 --- a/src/pico_ecs/pico_ecs/entities/EntityFactory.h +++ b/src/pico_ecs/pico_ecs/entities/EntityFactory.h @@ -2,6 +2,7 @@ #define ECS_BENCHMARKS_PICO_ECS_ENTITYFACTORY_H_ #include "base/components/DataComponent.h" +#include "base/components/HeroMonsterComponents.h" #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" #include "base/entities/EntityFactory.h" @@ -35,6 +36,9 @@ class EntityManager { ecs_id_t PositionComponent; ecs_id_t VelocityComponent; ecs_id_t DataComponent; + ecs_id_t PlayerComponent; + ecs_id_t HealthComponent; + ecs_id_t DamageComponent; [[nodiscard]] inline auto valid(ecs_id_t entity_id) { return ecs_is_ready(ecs.get(), entity_id); } @@ -46,6 +50,13 @@ class EntityManager { VelocityComponent_constructor, nullptr); DataComponent = ecs_register_component(ecs.get(), sizeof(ecs::benchmarks::base::components::DataComponent), nullptr, nullptr); + + PlayerComponent = + ecs_register_component(ecs.get(), sizeof(ecs::benchmarks::base::components::PlayerComponent), nullptr, nullptr); + HealthComponent = + ecs_register_component(ecs.get(), sizeof(ecs::benchmarks::base::components::HealthComponent), nullptr, nullptr); + DamageComponent = + ecs_register_component(ecs.get(), sizeof(ecs::benchmarks::base::components::DamageComponent), nullptr, nullptr); } }; } // namespace details diff --git a/src/pico_ecs/pico_ecs/entities/HeroMonsterEntityFactory.cpp b/src/pico_ecs/pico_ecs/entities/HeroMonsterEntityFactory.cpp new file mode 100644 index 0000000..a5164a4 --- /dev/null +++ b/src/pico_ecs/pico_ecs/entities/HeroMonsterEntityFactory.cpp @@ -0,0 +1,40 @@ +#include "HeroMonsterEntityFactory.h" +#include "base/components/HeroMonsterComponents.h" + +namespace ecs::benchmarks::pico_ecs::entities { + +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = ecs_create(registry.ecs.get()); + ecs_add(registry.ecs.get(), ret, registry.PlayerComponent, nullptr); + ecs_add(registry.ecs.get(), ret, registry.HealthComponent, nullptr); + ecs_add(registry.ecs.get(), ret, registry.DamageComponent, nullptr); + initComponents(registry, ret); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = ecs_create(registry.ecs.get()); + ecs_add(registry.ecs.get(), ret, registry.PlayerComponent, nullptr); + ecs_add(registry.ecs.get(), ret, registry.HealthComponent, nullptr); + ecs_add(registry.ecs.get(), ret, registry.DamageComponent, nullptr); + initComponents(registry, ret, PlayerType::Hero); + return ret; +} +HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& registry) { + using namespace ecs::benchmarks::base::components; + auto ret = ecs_create(registry.ecs.get()); + ecs_add(registry.ecs.get(), ret, registry.PlayerComponent, nullptr); + ecs_add(registry.ecs.get(), ret, registry.HealthComponent, nullptr); + ecs_add(registry.ecs.get(), ret, registry.DamageComponent, nullptr); + initComponents(registry, ret, PlayerType::Monster); + return ret; +} + +void HeroMonsterEntityFactory::addComponents(EntityManager& registry, Entity entity) { + ecs_add(registry.ecs.get(), entity, registry.PlayerComponent, nullptr); + ecs_add(registry.ecs.get(), entity, registry.HealthComponent, nullptr); + ecs_add(registry.ecs.get(), entity, registry.DamageComponent, nullptr); +} + +} // namespace ecs::benchmarks::pico_ecs::entities diff --git a/src/pico_ecs/pico_ecs/entities/HeroMonsterEntityFactory.h b/src/pico_ecs/pico_ecs/entities/HeroMonsterEntityFactory.h new file mode 100644 index 0000000..fde1edf --- /dev/null +++ b/src/pico_ecs/pico_ecs/entities/HeroMonsterEntityFactory.h @@ -0,0 +1,43 @@ +#ifndef ECS_BENCHMARKS_PICO_ECS_HEROMONSTERENTITYFACTORY_H_ +#define ECS_BENCHMARKS_PICO_ECS_HEROMONSTERENTITYFACTORY_H_ + +#include "EntityFactory.h" +#include "base/components/HeroMonsterComponents.h" +#include "base/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::pico_ecs::entities { + +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + details::EntityManager, ecs_id_t, ecs::benchmarks::base::components::PlayerComponent, + ecs::benchmarks::base::components::HealthComponent, ecs::benchmarks::base::components::DamageComponent> { +public: + Entity createRandom(EntityManager& registry) override; + Entity createHero(EntityManager& registry) override; + Entity createMonster(EntityManager& registry) override; + + void addComponents(EntityManager& registry, Entity entity) override; + + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponent(EntityManager& registry, Entity entity_id) override { + return *std::bit_cast( + ecs_get(registry.ecs.get(), entity_id, registry.PlayerComponent)); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& + getHealthComponent(EntityManager& registry, Entity entity_id) override { + return *std::bit_cast( + ecs_get(registry.ecs.get(), entity_id, registry.HealthComponent)); + } + + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& + getDamageComponent(EntityManager& registry, Entity entity_id) override { + return *std::bit_cast( + ecs_get(registry.ecs.get(), entity_id, registry.DamageComponent)); + } +}; + +} // namespace ecs::benchmarks::pico_ecs::entities + +#endif \ No newline at end of file diff --git a/src/pico_ecs/pico_ecs/systems/DataSystem.cpp b/src/pico_ecs/pico_ecs/systems/DataSystem.cpp index a98351d..ede6cd4 100644 --- a/src/pico_ecs/pico_ecs/systems/DataSystem.cpp +++ b/src/pico_ecs/pico_ecs/systems/DataSystem.cpp @@ -2,23 +2,30 @@ #include "base/components/DataComponent.h" #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" +#include +#include +#include namespace ecs::benchmarks::pico_ecs::systems { +auto DataSystem::updateData(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t { + (void)ecs; + (void)dt; + EntityManager& uregistry = *std::bit_cast(udata); + + for (auto entity_id : entities) { + auto& data = *std::bit_cast<::ecs::benchmarks::base::components::DataComponent*>( + ecs_get(uregistry.ecs.get(), entity_id, uregistry.DataComponent)); + ::ecs::benchmarks::base::systems::DataSystem::updateData(data, dt); + } + + return 0; +} + void DataSystem::init(EntityManager& registry) { auto system_update = [](ecs_t* ecs, ecs_id_t* entities, int entity_count, ecs_dt_t dt, void* udata) -> ecs_ret_t { - (void)ecs; - (void)dt; - EntityManager& uregistry = *reinterpret_cast(udata); - - for (int id = 0; id < entity_count; id++) { - auto entity_id = entities[id]; - auto& data = *reinterpret_cast( - ecs_get(uregistry.ecs.get(), entity_id, uregistry.DataComponent)); - DataSystem::updateData(data, dt); - } - - return 0; + assert(entity_count >= 0); + return updateData(ecs, std::span{entities, static_cast(entity_count)}, dt, udata); }; /// @NOTE: lets hope registry is still alive :) diff --git a/src/pico_ecs/pico_ecs/systems/DataSystem.h b/src/pico_ecs/pico_ecs/systems/DataSystem.h index 01c2b33..2481563 100644 --- a/src/pico_ecs/pico_ecs/systems/DataSystem.h +++ b/src/pico_ecs/pico_ecs/systems/DataSystem.h @@ -4,6 +4,7 @@ #include "base/systems/DataSystem.h" #include "pico_ecs/entities/EntityFactory.h" #include +#include namespace ecs::benchmarks::pico_ecs::systems { @@ -18,6 +19,8 @@ class DataSystem final private: ecs_id_t m_system; + + static auto updateData(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t; }; } // namespace ecs::benchmarks::pico_ecs::systems diff --git a/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.cpp b/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.cpp index e112ea7..e91fab5 100644 --- a/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.cpp +++ b/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.cpp @@ -2,31 +2,37 @@ #include "base/components/DataComponent.h" #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" +#include #include +#include namespace ecs::benchmarks::pico_ecs::systems { +auto MoreComplexSystem::updateMoreComplex(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) + -> ecs_ret_t { + (void)ecs; + (void)dt; + details::MoreComplexSystemContext& context = *std::bit_cast(udata); + + assert(context.registry); + assert(context.system); + + for (auto entity_id : entities) { + auto& position = *std::bit_cast( + ecs_get(context.registry->ecs.get(), entity_id, context.registry->PositionComponent)); + auto& direction = *std::bit_cast( + ecs_get(context.registry->ecs.get(), entity_id, context.registry->VelocityComponent)); + auto& data = *std::bit_cast( + ecs_get(context.registry->ecs.get(), entity_id, context.registry->DataComponent)); + context.system->updateComponents(position, direction, data); + } + + return 0; +} void MoreComplexSystem::init(EntityManager& registry) { auto system_update = [](ecs_t* ecs, ecs_id_t* entities, int entity_count, ecs_dt_t dt, void* udata) -> ecs_ret_t { - (void)ecs; - (void)dt; - details::MoreComplexSystemContext& context = *reinterpret_cast(udata); - - assert(context.registry); - assert(context.system); - - for (int id = 0; id < entity_count; id++) { - auto entity_id = entities[id]; - auto& position = *reinterpret_cast( - ecs_get(context.registry->ecs.get(), entity_id, context.registry->PositionComponent)); - auto& direction = *reinterpret_cast( - ecs_get(context.registry->ecs.get(), entity_id, context.registry->VelocityComponent)); - auto& data = *reinterpret_cast( - ecs_get(context.registry->ecs.get(), entity_id, context.registry->DataComponent)); - context.system->updateComponents(position, direction, data); - } - - return 0; + assert(entity_count >= 0); + return updateMoreComplex(ecs, std::span{entities, static_cast(entity_count)}, dt, udata); }; /// @NOTE: lets hope registry is still alive :) @@ -39,9 +45,66 @@ void MoreComplexSystem::init(EntityManager& registry) { ecs_require_component(registry.ecs.get(), m_system, registry.VelocityComponent); ecs_require_component(registry.ecs.get(), m_system, registry.DataComponent); } - void MoreComplexSystem::update(EntityManager& registry, TimeDelta dt) { ecs_update_system(registry.ecs.get(), m_system, dt); } + +auto HealthSystem::updateHealth(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t { + (void)ecs; + (void)dt; + EntityManager& uregistry = *std::bit_cast(udata); + + for (auto entity_id : entities) { + auto& health = *std::bit_cast( + ecs_get(uregistry.ecs.get(), entity_id, uregistry.HealthComponent)); + ::ecs::benchmarks::base::systems::HealthSystem::updateHealth(health); + } + + return 0; +} +void HealthSystem::init(EntityManager& registry) { + auto system_update = [](ecs_t* ecs, ecs_id_t* entities, int entity_count, ecs_dt_t dt, void* udata) -> ecs_ret_t { + assert(entity_count >= 0); + return updateHealth(ecs, std::span{entities, static_cast(entity_count)}, dt, udata); + }; + + /// @NOTE: lets hope registry is still alive :) + m_system = ecs_register_system(registry.ecs.get(), system_update, nullptr, nullptr, ®istry); + ecs_require_component(registry.ecs.get(), m_system, registry.HealthComponent); +} +void HealthSystem::update(EntityManager& registry, TimeDelta dt) { + ecs_update_system(registry.ecs.get(), m_system, dt); +} + +auto DamageSystem::updateDamage(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t { + (void)ecs; + (void)dt; + EntityManager& uregistry = *std::bit_cast(udata); + + for (auto entity_id : entities) { + auto& health = *std::bit_cast( + ecs_get(uregistry.ecs.get(), entity_id, uregistry.HealthComponent)); + const auto& damage = *std::bit_cast( + ecs_get(uregistry.ecs.get(), entity_id, uregistry.DamageComponent)); + ::ecs::benchmarks::base::systems::DamageSystem::updateDamage(health, damage); + } + + return 0; +} +void DamageSystem::init(EntityManager& registry) { + auto system_update = [](ecs_t* ecs, ecs_id_t* entities, int entity_count, ecs_dt_t dt, void* udata) -> ecs_ret_t { + assert(entity_count >= 0); + return updateDamage(ecs, std::span{entities, static_cast(entity_count)}, dt, udata); + }; + + /// @NOTE: lets hope registry is still alive :) + m_system = ecs_register_system(registry.ecs.get(), system_update, nullptr, nullptr, ®istry); + ecs_require_component(registry.ecs.get(), m_system, registry.HealthComponent); + ecs_require_component(registry.ecs.get(), m_system, registry.DamageComponent); +} +void DamageSystem::update(EntityManager& registry, TimeDelta dt) { + ecs_update_system(registry.ecs.get(), m_system, dt); +} + } // namespace ecs::benchmarks::pico_ecs::systems \ No newline at end of file diff --git a/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.h b/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.h index 5246733..be3d52a 100644 --- a/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.h +++ b/src/pico_ecs/pico_ecs/systems/MoreComplexSystem.h @@ -1,9 +1,11 @@ #ifndef ECS_BENCHMARKS_PICO_ECS_MORECOMPLEXSYSTEM_H_ #define ECS_BENCHMARKS_PICO_ECS_MORECOMPLEXSYSTEM_H_ +#include "base/systems/HeroMonsterSystems.h" #include "base/systems/MoreComplexSystem.h" #include "pico_ecs/entities/EntityFactory.h" #include +#include namespace ecs::benchmarks::pico_ecs::systems { @@ -28,6 +30,38 @@ class MoreComplexSystem final : public ecs::benchmarks::base::systems::MoreCompl private: ecs_id_t m_system; details::MoreComplexSystemContext m_context; + + static auto updateMoreComplex(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t; +}; + +class HealthSystem final + : public ecs::benchmarks::base::systems::HealthSystem { +public: + void init(EntityManager& /*registry*/) override; + void update(EntityManager& registry, TimeDelta dt) override; + + [[nodiscard]] inline ecs_id_t id() const noexcept { return m_system; } + +private: + ecs_id_t m_system; + + static auto updateHealth(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t; +}; + +class DamageSystem final + : public ecs::benchmarks::base::systems::DamageSystem { +public: + void init(EntityManager& /*registry*/) override; + void update(EntityManager& registry, TimeDelta dt) override; + + [[nodiscard]] inline ecs_id_t id() const noexcept { return m_system; } + +private: + ecs_id_t m_system; + + static auto updateDamage(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t; }; } // namespace ecs::benchmarks::pico_ecs::systems diff --git a/src/pico_ecs/pico_ecs/systems/MovementSystem.cpp b/src/pico_ecs/pico_ecs/systems/MovementSystem.cpp index 86c5b25..1e56964 100644 --- a/src/pico_ecs/pico_ecs/systems/MovementSystem.cpp +++ b/src/pico_ecs/pico_ecs/systems/MovementSystem.cpp @@ -1,25 +1,32 @@ #include "MovementSystem.h" #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" +#include +#include +#include namespace ecs::benchmarks::pico_ecs::systems { +auto MovementSystem::updateMovement(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t { + (void)ecs; + (void)dt; + EntityManager& uregistry = *std::bit_cast(udata); + + for (auto entity_id : entities) { + auto& position = *std::bit_cast<::ecs::benchmarks::base::components::PositionComponent*>( + ecs_get(uregistry.ecs.get(), entity_id, uregistry.PositionComponent)); + const auto& direction = *std::bit_cast<::ecs::benchmarks::base::components::VelocityComponent*>( + ecs_get(uregistry.ecs.get(), entity_id, uregistry.VelocityComponent)); + ::ecs::benchmarks::base::systems::MovementSystem::updatePosition(position, direction, dt); + } + + return 0; +} + void MovementSystem::init(EntityManager& registry) { auto system_update = [](ecs_t* ecs, ecs_id_t* entities, int entity_count, ecs_dt_t dt, void* udata) -> ecs_ret_t { - (void)ecs; - (void)dt; - EntityManager& uregistry = *reinterpret_cast(udata); - - for (int id = 0; id < entity_count; id++) { - auto entity_id = entities[id]; - auto& position = *reinterpret_cast( - ecs_get(uregistry.ecs.get(), entity_id, uregistry.PositionComponent)); - auto& direction = *reinterpret_cast( - ecs_get(uregistry.ecs.get(), entity_id, uregistry.VelocityComponent)); - MovementSystem::updatePosition(position, direction, dt); - } - - return 0; + assert(entity_count >= 0); + return updateMovement(ecs, std::span{entities, static_cast(entity_count)}, dt, udata); }; /// @NOTE: lets hope registry is still alive :) diff --git a/src/pico_ecs/pico_ecs/systems/MovementSystem.h b/src/pico_ecs/pico_ecs/systems/MovementSystem.h index 69d2966..fbfa5bc 100644 --- a/src/pico_ecs/pico_ecs/systems/MovementSystem.h +++ b/src/pico_ecs/pico_ecs/systems/MovementSystem.h @@ -4,6 +4,7 @@ #include "base/systems/MovementSystem.h" #include "pico_ecs/entities/EntityFactory.h" #include +#include namespace ecs::benchmarks::pico_ecs::systems { @@ -18,6 +19,8 @@ class MovementSystem final private: ecs_id_t m_system; + + static auto updateMovement(ecs_t* ecs, std::span entities, ecs_dt_t dt, void* udata) -> ecs_ret_t; }; } // namespace ecs::benchmarks::pico_ecs::systems diff --git a/test/tests/application/base.h b/test/tests/application/base.h index 473aada..1d2ab0c 100644 --- a/test/tests/application/base.h +++ b/test/tests/application/base.h @@ -37,7 +37,7 @@ struct Application_Fixture { const auto& comp = m_entity_factory.getComponentOne(app.getEntities(), entity); AND_THEN("component.x is updated") { - REQUIRE(comp.x > 0.0F); + REQUIRE(comp.x > 0.0); } } } diff --git a/test/tests/entity_factory/base.h b/test/tests/entity_factory/base.h index 0fa9ded..34bceef 100644 --- a/test/tests/entity_factory/base.h +++ b/test/tests/entity_factory/base.h @@ -81,6 +81,39 @@ struct EntityFactory_Fixture { } }; +template +struct HeroMonsterEntityFactory_Fixture { + using EntityManager = EntityFactory::EntityManager; + using Entity = EntityFactory::Entity; + + EntityFactory m_entity_factory; + + void testCreateEntity(EntityManager& registry) { + auto entity = m_entity_factory.createRandom(registry); + + THEN("valid entity") { + REQUIRE(registry.valid(entity)); + } + } + + + void testGetPlayerComponent(EntityManager& registry) { + GIVEN("one entity") { + auto entity = m_entity_factory.createRandom(registry); + REQUIRE(registry.valid(entity)); + + WHEN("get player component") { + const auto& player = m_entity_factory.getPlayerComponent(registry, entity); + + THEN("got player component") { + ((void)player); + // REQUIRE(player); + } + } + } + } +}; + } // namespace ecs::benchmarks #endif // ECS_BENCHMARK_TESTS_ENTITY_FACTORY_BASE_H diff --git a/test/tests/entity_factory/entt_test.cpp b/test/tests/entity_factory/entt_test.cpp index 3360477..fc54e68 100644 --- a/test/tests/entity_factory/entt_test.cpp +++ b/test/tests/entity_factory/entt_test.cpp @@ -1,5 +1,6 @@ #include "base.h" #include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" #include #include @@ -35,4 +36,22 @@ TEMPLATE_TEST_CASE_METHOD(ecs::benchmarks::EntityFactory_Fixture, "Test EntityFa } } +TEMPLATE_TEST_CASE_METHOD(ecs::benchmarks::HeroMonsterEntityFactory_Fixture, "Test HeroMonsterEntityFactory for entt", + "[template][entt][entity_factory][hero][monster]", + ecs::benchmarks::entt::entities::HeroMonsterEntityFactory) { + GIVEN("HeroMonsterEntityFactory") { + ecs::benchmarks::HeroMonsterEntityFactory_Fixture entity_factory_fixture; + // auto& entity_factory = entity_factory_fixture.m_entity_factory; + ::entt::registry registry; + + WHEN("create entity") { + entity_factory_fixture.testCreateEntity(registry); + } + + WHEN("get one component") { + entity_factory_fixture.testGetPlayerComponent(registry); + } + } +} + } // namespace ecs::benchmarks::entt \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index ec8f260..651a12e 100755 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "ecs-benchmark", - "version-string": "4.7.4", + "version-string": "5.0.0", "description": "Benchmarks of common ECS (Entity-Component-System)-Frameworks in C++ (or C)", "dependencies": [ "benchmark",