diff --git a/CMakeLists.txt b/CMakeLists.txt index fd0380b..56b7f0d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ cpmaddpackage( GITHUB_REPOSITORY aminya/project_options VERSION - 0.34.0 + 0.35.1 # GIT_TAG main DOWNLOAD_ONLY) if(project_options_ADDED) diff --git a/README.md b/README.md index dd6b017..d02a9d3 100644 --- a/README.md +++ b/README.md @@ -32,26 +32,28 @@ The results of these benchmarks should be used as a starting point for your own _Graph shows cost per entity, tables shows total cost. lower is faster._ -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:-------------|:-----------|:--------|:-----------|:-----------|:---------------| -| Update 8 entities with 7 Systems | 355ns | 693ns | 199ns | 253ns | **169ns** | 53373ns | 2332ns | 176ns | 390ns | 393ns | -| Update 16 entities with 7 Systems | 360ns | 834ns | 184ns | **176ns** | 210ns | 51544ns | 2198ns | 181ns | 315ns | 335ns | -| Update 32 entities with 7 Systems | 595ns | 1576ns | 286ns | **230ns** | 383ns | 52746ns | 2266ns | 323ns | 382ns | 389ns | -| Update 64 entities with 7 Systems | 1052ns | 2961ns | 476ns | **343ns** | 720ns | 51403ns | 2402ns | 559ns | 518ns | 518ns | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update 1 entities with 7 Systems | 124ns | 135ns | 78ns | 128ns | 41ns | 240ns | 1921ns | 65ns | 222ns | 231ns | +| Update 4 entities with 7 Systems | 212ns | 345ns | 126ns | 179ns | 115ns | 460ns | 3347ns | 122ns | 410ns | 392ns | +| Update 8 entities with 7 Systems | 334ns | 632ns | 181ns | 255ns | 165ns | 521ns | 3452ns | 179ns | 455ns | 454ns | +| Update 16 entities with 7 Systems | 332ns | 835ns | 177ns | 181ns | 220ns | 474ns | 3187ns | 190ns | 356ns | 349ns | +| Update 32 entities with 7 Systems | 559ns | 1618ns | 268ns | 235ns | 370ns | 545ns | 3231ns | 326ns | 425ns | 416ns | +| Update 64 entities with 7 Systems | 1028ns | 3067ns | 471ns | 346ns | 712ns | 674ns | 3399ns | 563ns | 568ns | 571ns | -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:-----------------|:-----------|:--------------|:-------------------| -| Update 256 entities with 7 Systems | 7us | 21us | 4us | 4us | 4us | 52us | 3us | 4us | **2us** | **2us** | -| Update ~1K entities with 7 Systems | 34us | 84us | 18us | 21us | 16us | 64us | **9us** | 18us | 10us | 10us | -| Update ~4K entities with 7 Systems | 137us | 347us | 92us | 89us | 68us | 86us | **29us** | 75us | 44us | 46us | -| Update ~16K entities with 7 Systems | 550us | 1385us | 391us | 356us | 296us | 181us | **124us** | 329us | 218us | 215us | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update 256 entities with 7 Systems | 7us | 21us | 3us | 4us | 4us | 2us | 4us | 4us | 2us | 2us | +| Update ~1K entities with 7 Systems | 31us | 87us | 18us | 21us | 16us | 7us | 10us | 17us | 10us | 9us | +| Update ~4K entities with 7 Systems | 140us | 355us | 93us | 89us | 70us | 28us | 32us | 80us | 45us | 46us | +| Update ~16K entities with 7 Systems | 576us | 1439us | 407us | 352us | 297us | 122us | 116us | 310us | 215us | 216us | -| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------------------|:--------------|:---------|:---------|:---------------| -| Update ~65K entities with 7 Systems | 2ms | 5ms | 1ms | 1ms | 1ms | **0ms** | **0ms** | 1ms | 1ms | 1ms | -| Update 262K entities with 7 Systems | 10ms | 23ms | 8ms | 6ms | 6ms | **3ms** | **3ms** | 6ms | 7ms | 8ms | -| Update ~1M entities with 7 Systems | 40ms | 92ms | 36ms | 26ms | 27ms | **14ms** | 19ms | 23ms | 32ms | 32ms | -| Update ~2M entities with 7 Systems | 82ms | 176ms | 88ms | 53ms | 55ms | **27ms** | 37ms | 47ms | 65ms | 65ms | +| | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update ~65K entities with 7 Systems | 2ms | 5ms | 1ms | 1ms | 1ms | 0ms | 0ms | 1ms | 1ms | 1ms | +| Update 262K entities with 7 Systems | 10ms | 24ms | 8ms | 6ms | 6ms | 3ms | 4ms | 5ms | 7ms | 7ms | +| Update ~1M entities with 7 Systems | 41ms | 95ms | 35ms | 26ms | 27ms | 16ms | 20ms | 23ms | 31ms | 31ms | +| Update ~2M entities with 7 Systems | 84ms | 183ms | 86ms | 52ms | 54ms | 32ms | 38ms | 49ms | 62ms | 65ms | @@ -110,10 +112,10 @@ Benchmarks for more common features, such as "Creating entities", "Adding and re ### Environment -* **OS:** Linux 64-Bit (Kernel: 6.7.5) +* **OS:** Linux 64-Bit (Kernel: 6.9.9) * **CPU:** 3.13GHz @ 12Cores * **RAM:** 47GB -* **Compiler:** gcc (GCC) 13.2.1 +* **Compiler:** gcc (GCC) 14.1.1 --- @@ -127,24 +129,26 @@ _Graph shows cost per entity, tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:------------------------------------------|:----------|:-------|:----------|:-----------|:---------|:-----------|:-----------| -| Create 8 entities with two Components | 2324ns | 3636ns | 10465ns | 3151ns | 439817ns | 1605ns | 8251ns | -| Create 16 entities with two Components | 2980ns | 4038ns | 10759ns | 3776ns | 445037ns | 1751ns | 9325ns | -| Create 32 entities with two Components | 4240ns | 4741ns | 11370ns | 4858ns | 447287ns | 2083ns | 11289ns | -| Create 64 entities with two Components | 6666ns | 6107ns | 12342ns | 6990ns | 454778ns | 2741ns | 15517ns | +| Create 1 entities with two Components | 1457ns | 2868ns | 10034ns | 2456ns | 401342ns | 1334ns | 4512ns | +| Create 4 entities with two Components | 1776ns | 3182ns | 10260ns | 2819ns | 405156ns | 1419ns | 4894ns | +| Create 8 entities with two Components | 2144ns | 3467ns | 10459ns | 3148ns | 407955ns | 1501ns | 5399ns | +| Create 16 entities with two Components | 2820ns | 3801ns | 10748ns | 3722ns | 408108ns | 1650ns | 6339ns | +| Create 32 entities with two Components | 4036ns | 4476ns | 11280ns | 4817ns | 414509ns | 1954ns | 8284ns | +| Create 64 entities with two Components | 6410ns | 5742ns | 12245ns | 6935ns | 422601ns | 2563ns | 12306ns | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Create 256 entities with two Components | 20us | 13us | 17us | 19us | 500us | 6us | 38us | -| Create ~1K entities with two Components | 77us | 44us | 34us | 68us | 681us | 22us | 135us | -| Create ~4K entities with two Components | 303us | 167us | 105us | 269us | 1447us | 95us | 542us | -| Create ~16K entities with two Components | 1203us | 665us | 376us | 1115us | 4468us | 379us | 2762us | +| Create 256 entities with two Components | 20us | 13us | 16us | 19us | 486us | 6us | 35us | +| Create ~1K entities with two Components | 74us | 41us | 33us | 68us | 740us | 20us | 124us | +| Create ~4K entities with two Components | 292us | 155us | 100us | 264us | 1813us | 90us | 481us | +| Create ~16K entities with two Components | 1163us | 625us | 357us | 1047us | 5902us | 355us | 1929us | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Create ~65K entities with two Components | 4ms | 2ms | 1ms | 4ms | 16ms | 1ms | 20ms | -| Create 262K entities with two Components | 19ms | 11ms | 8ms | 18ms | 63ms | 7ms | 356ms | -| Create ~1M entities with two Components | 92ms | 71ms | 55ms | 87ms | 282ms | 45ms | 5358ms | -| Create ~2M entities with two Components | 180ms | 133ms | 102ms | 168ms | 544ms | 67ms | 23492ms | +| Create ~65K entities with two Components | 4ms | 2ms | 1ms | 4ms | 21ms | 1ms | 7ms | +| Create 262K entities with two Components | 18ms | 10ms | 8ms | 17ms | 89ms | 6ms | 35ms | +| Create ~1M entities with two Components | 91ms | 66ms | 55ms | 88ms | 371ms | 44ms | 147ms | +| Create ~2M entities with two Components | 180ms | 128ms | 103ms | 172ms | 721ms | 74ms | 303ms | @@ -157,24 +161,26 @@ _Graph shows cost per entity, tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------------|:----------|:-------|:----------|:---------|:-----------|:-----------| -| Destroy 8 entities with two components | 1567ns | 1395ns | 2002ns | 412408ns | 1476ns | 4611ns | -| Destroy 16 entities with two components | 1939ns | 1674ns | 2734ns | 395578ns | 1543ns | 5745ns | -| Destroy 32 entities with two components | 2658ns | 2254ns | 4182ns | 395956ns | 1684ns | 9033ns | -| Destroy 64 entities with two components | 4236ns | 3381ns | 7040ns | 397542ns | 1979ns | 13523ns | +| Destroy 1 entities with two components | 1123ns | 1053ns | 1174ns | 349451ns | 1318ns | 2940ns | +| Destroy 4 entities with two components | 1266ns | 1123ns | 1492ns | 350054ns | 1355ns | 3212ns | +| Destroy 8 entities with two components | 1455ns | 1312ns | 1902ns | 351086ns | 1374ns | 3642ns | +| Destroy 16 entities with two components | 1783ns | 1609ns | 2621ns | 351077ns | 1420ns | 4603ns | +| Destroy 32 entities with two components | 2476ns | 2425ns | 4029ns | 351619ns | 1553ns | 6430ns | +| Destroy 64 entities with two components | 3937ns | 3701ns | 6836ns | 353878ns | 1728ns | 10340ns | | | EntityX | EnTT | Ginseng | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------------|:----------|:-------|:----------|:--------|:-----------|:-----------| -| Destroy 256 entities with two components | 13us | 10us | 23us | 406us | 3us | 37us | -| Destroy ~1K entities with two components | 50us | 37us | 93us | 445us | 10us | 135us | -| Destroy ~4K entities with two components | 203us | 150us | 364us | 598us | 38us | 538us | -| Destroy ~16K entities with two components | 837us | 599us | 1441us | 1231us | 151us | 2168us | +| Destroy 256 entities with two components | 12us | 11us | 23us | 362us | 2us | 30us | +| Destroy ~1K entities with two components | 48us | 43us | 89us | 400us | 7us | 113us | +| Destroy ~4K entities with two components | 198us | 159us | 353us | 553us | 29us | 463us | +| Destroy ~16K entities with two components | 811us | 633us | 1408us | 1162us | 111us | 1862us | | | EntityX | EnTT | Ginseng | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------------|:----------|:-------|:----------|:--------|:-----------|:-----------| -| Destroy ~65K entities with two components | 3ms | 2ms | 5ms | 3ms | 0ms | 8ms | -| Destroy 262K entities with two components | 14ms | 9ms | 23ms | 15ms | 2ms | 38ms | -| Destroy ~1M entities with two components | 64ms | 43ms | 99ms | 57ms | 13ms | 195ms | -| Destroy ~2M entities with two components | 128ms | 84ms | 193ms | 113ms | 23ms | 442ms | +| Destroy ~65K entities with two components | 3ms | 2ms | 5ms | 3ms | 0ms | 7ms | +| Destroy 262K entities with two components | 13ms | 10ms | 23ms | 16ms | 1ms | 33ms | +| Destroy ~1M entities with two components | 63ms | 44ms | 98ms | 59ms | 10ms | 186ms | +| Destroy ~2M entities with two components | 125ms | 86ms | 189ms | 114ms | 18ms | 409ms | @@ -187,24 +193,26 @@ _Graph shows cost per entity, tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:---------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack one component in 8 entities | 29ns | 28ns | 13ns | 92ns | 203ns | 15ns | 22ns | -| Unpack one component in 16 entities | 58ns | 56ns | 31ns | 180ns | 403ns | 34ns | 46ns | -| Unpack one component in 32 entities | 115ns | 116ns | 59ns | 394ns | 799ns | 64ns | 89ns | -| Unpack one component in 64 entities | 231ns | 226ns | 117ns | 756ns | 1596ns | 122ns | 175ns | +| Unpack one component in 1 entities | 3ns | 3ns | 1ns | 10ns | 26ns | 1ns | 2ns | +| Unpack one component in 4 entities | 14ns | 12ns | 6ns | 48ns | 105ns | 5ns | 10ns | +| Unpack one component in 8 entities | 28ns | 25ns | 13ns | 88ns | 205ns | 11ns | 22ns | +| Unpack one component in 16 entities | 57ns | 50ns | 27ns | 172ns | 400ns | 26ns | 43ns | +| Unpack one component in 32 entities | 115ns | 104ns | 60ns | 335ns | 800ns | 48ns | 82ns | +| Unpack one component in 64 entities | 231ns | 204ns | 112ns | 651ns | 1596ns | 89ns | 163ns | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:---------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| | Unpack one component in 256 entities | 0us | 0us | 0us | 2us | 6us | 0us | 0us | -| Unpack one component in ~1K entities | 3us | 3us | 1us | 11us | 25us | 1us | 2us | -| Unpack one component in ~4K entities | 14us | 14us | 7us | 66us | 101us | 7us | 11us | -| Unpack one component in ~16K entities | 59us | 56us | 28us | 268us | 407us | 29us | 45us | +| Unpack one component in ~1K entities | 3us | 3us | 1us | 10us | 25us | 1us | 2us | +| Unpack one component in ~4K entities | 14us | 12us | 7us | 41us | 101us | 5us | 10us | +| Unpack one component in ~16K entities | 59us | 51us | 28us | 195us | 417us | 21us | 42us | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:---------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| | Unpack one component in ~65K entities | 0ms | 0ms | 0ms | 0ms | 1ms | 0ms | 0ms | -| Unpack one component in 262K entities | 1ms | 0ms | 0ms | 3ms | 6ms | 0ms | 1ms | -| Unpack one component in ~1M entities | 4ms | 4ms | 2ms | 12ms | 26ms | 1ms | 4ms | -| Unpack one component in ~2M entities | 9ms | 8ms | 4ms | 25ms | 52ms | 3ms | 8ms | +| Unpack one component in 262K entities | 1ms | 0ms | 0ms | 2ms | 6ms | 0ms | 0ms | +| Unpack one component in ~1M entities | 4ms | 3ms | 2ms | 11ms | 27ms | 1ms | 3ms | +| Unpack one component in ~2M entities | 9ms | 7ms | 4ms | 23ms | 52ms | 2ms | 7ms | **Note:** @@ -221,24 +229,26 @@ _Graph shows cost per entity, tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:----------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack two components in 8 entities | 57ns | 74ns | 27ns | 181ns | 409ns | 26ns | 40ns | -| Unpack two components in 16 entities | 115ns | 139ns | 55ns | 354ns | 816ns | 55ns | 72ns | -| Unpack two components in 32 entities | 231ns | 269ns | 113ns | 707ns | 1628ns | 105ns | 141ns | -| Unpack two components in 64 entities | 465ns | 536ns | 221ns | 1411ns | 3254ns | 204ns | 275ns | +| Unpack two components in 1 entities | 7ns | 6ns | 3ns | 22ns | 51ns | 2ns | 4ns | +| Unpack two components in 4 entities | 28ns | 25ns | 13ns | 112ns | 204ns | 11ns | 16ns | +| Unpack two components in 8 entities | 57ns | 50ns | 27ns | 211ns | 406ns | 21ns | 38ns | +| Unpack two components in 16 entities | 115ns | 104ns | 54ns | 440ns | 802ns | 47ns | 71ns | +| Unpack two components in 32 entities | 231ns | 204ns | 109ns | 697ns | 1617ns | 88ns | 138ns | +| Unpack two components in 64 entities | 462ns | 404ns | 223ns | 1384ns | 3219ns | 171ns | 266ns | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:----------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack two components in 256 entities | 1us | 2us | 0us | 5us | 12us | 0us | 1us | -| Unpack two components in ~1K entities | 7us | 8us | 3us | 22us | 51us | 3us | 4us | -| Unpack two components in ~4K entities | 29us | 34us | 14us | 89us | 208us | 12us | 17us | -| Unpack two components in ~16K entities | 118us | 137us | 57us | 372us | 831us | 51us | 70us | +| Unpack two components in 256 entities | 1us | 1us | 0us | 5us | 12us | 0us | 1us | +| Unpack two components in ~1K entities | 7us | 6us | 3us | 22us | 50us | 2us | 4us | +| Unpack two components in ~4K entities | 29us | 25us | 14us | 111us | 203us | 10us | 17us | +| Unpack two components in ~16K entities | 118us | 103us | 56us | 452us | 813us | 42us | 67us | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:----------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack two components in ~65K entities | 0ms | 0ms | 0ms | 1ms | 3ms | 0ms | 0ms | -| Unpack two components in 262K entities | 2ms | 2ms | 0ms | 6ms | 13ms | 0ms | 1ms | -| Unpack two components in ~1M entities | 8ms | 9ms | 3ms | 25ms | 53ms | 3ms | 5ms | -| Unpack two components in ~2M entities | 18ms | 18ms | 7ms | 51ms | 106ms | 6ms | 10ms | +| Unpack two components in ~65K entities | 0ms | 0ms | 0ms | 2ms | 3ms | 0ms | 0ms | +| Unpack two components in 262K entities | 2ms | 1ms | 0ms | 9ms | 13ms | 0ms | 1ms | +| Unpack two components in ~1M entities | 9ms | 6ms | 3ms | 39ms | 51ms | 2ms | 5ms | +| Unpack two components in ~2M entities | 18ms | 13ms | 7ms | 74ms | 105ms | 5ms | 11ms | @@ -257,24 +267,26 @@ _Graph shows cost per entity, tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack three components in 8 entities | 60ns | 116ns | 48ns | 180ns | 1174ns | 41ns | 79ns | -| Unpack three components in 16 entities | 118ns | 233ns | 97ns | 358ns | 2342ns | 76ns | 152ns | -| Unpack three components in 32 entities | 240ns | 455ns | 199ns | 702ns | 4674ns | 146ns | 299ns | -| Unpack three components in 64 entities | 474ns | 904ns | 396ns | 1399ns | 9354ns | 287ns | 591ns | -| Unpack three components in 128 entities | 956ns | 1795ns | 788ns | 4286ns | 18657ns | 567ns | 1176ns | +| Unpack three components in 1 entities | 7ns | 12ns | 6ns | 22ns | 104ns | 3ns | 9ns | +| Unpack three components in 2 entities | 14ns | 24ns | 12ns | 44ns | 212ns | 7ns | 18ns | +| Unpack three components in 8 entities | 57ns | 99ns | 47ns | 181ns | 842ns | 34ns | 75ns | +| Unpack three components in 16 entities | 115ns | 195ns | 96ns | 353ns | 1644ns | 63ns | 144ns | +| Unpack three components in 32 entities | 231ns | 387ns | 195ns | 697ns | 3276ns | 121ns | 278ns | +| Unpack three components in 64 entities | 464ns | 772ns | 385ns | 1399ns | 6569ns | 236ns | 549ns | +| Unpack three components in 128 entities | 930ns | 1548ns | 772ns | 2792ns | 13068ns | 467ns | 1093ns | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack three components in 512 entities | 3us | 7us | 3us | 11us | 74us | 2us | 4us | -| Unpack three components in ~2K entities | 14us | 29us | 12us | 45us | 300us | 9us | 18us | -| Unpack three components in ~8K entities | 60us | 117us | 50us | 186us | 1195us | 35us | 76us | +| Unpack three components in 512 entities | 3us | 6us | 3us | 11us | 52us | 1us | 4us | +| Unpack three components in ~2K entities | 14us | 24us | 12us | 44us | 209us | 7us | 17us | +| Unpack three components in ~8K entities | 59us | 100us | 50us | 196us | 859us | 29us | 70us | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:------------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Unpack three components in ~32K entities | 0ms | 0ms | 0ms | 0ms | 4ms | 0ms | 0ms | -| Unpack three components in 131K entities | 1ms | 1ms | 0ms | 3ms | 20ms | 0ms | 1ms | -| Unpack three components in 524K entities | 4ms | 8ms | 4ms | 12ms | 76ms | 2ms | 6ms | -| Unpack three components in ~1M entities | 9ms | 16ms | 7ms | 24ms | 154ms | 4ms | 12ms | +| Unpack three components in ~32K entities | 0ms | 0ms | 0ms | 0ms | 3ms | 0ms | 0ms | +| Unpack three components in 131K entities | 1ms | 1ms | 0ms | 2ms | 13ms | 0ms | 1ms | +| Unpack three components in 524K entities | 4ms | 6ms | 3ms | 13ms | 53ms | 1ms | 5ms | +| Unpack three components in ~1M entities | 9ms | 13ms | 7ms | 24ms | 109ms | 3ms | 11ms | @@ -295,24 +307,26 @@ _Graph shows cost per entity, tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | Flecs | pico_ecs | gaia-ecs | |:---------------------------------------------|:----------|:-------|:----------|:--------|:-----------|:-----------| -| Remove and Add a Component in 8 entities | 125ns | 229ns | 97ns | 1738ns | 76ns | 1808ns | -| Remove and Add a Component in 16 entities | 244ns | 449ns | 186ns | 3430ns | 146ns | 3575ns | -| Remove and Add a Component in 32 entities | 483ns | 927ns | 365ns | 6807ns | 287ns | 7424ns | -| Remove and Add a Component in 64 entities | 961ns | 1944ns | 727ns | 13662ns | 567ns | 15024ns | +| Remove and Add a Component in 1 entities | 15ns | 24ns | 10ns | 258ns | 7ns | 119ns | +| Remove and Add a Component in 4 entities | 59ns | 107ns | 42ns | 946ns | 39ns | 522ns | +| Remove and Add a Component in 8 entities | 125ns | 203ns | 90ns | 1892ns | 69ns | 1031ns | +| Remove and Add a Component in 16 entities | 244ns | 397ns | 176ns | 3799ns | 131ns | 2058ns | +| Remove and Add a Component in 32 entities | 480ns | 781ns | 348ns | 7573ns | 257ns | 4102ns | +| Remove and Add a Component in 64 entities | 952ns | 1554ns | 959ns | 15096ns | 507ns | 8220ns | | | EntityX | EnTT | Ginseng | Flecs | pico_ecs | gaia-ecs | |:---------------------------------------------|:----------|:-------|:----------|:--------|:-----------|:-----------| -| Remove and Add a Component in 256 entities | 3us | 7us | 2us | 54us | 2us | 57us | -| Remove and Add a Component in ~1K entities | 15us | 28us | 11us | 217us | 9us | 227us | -| Remove and Add a Component in ~4K entities | 61us | 113us | 50us | 888us | 35us | 914us | -| Remove and Add a Component in ~16K entities | 245us | 451us | 188us | 3489us | 143us | 4239us | +| Remove and Add a Component in 256 entities | 3us | 6us | 3us | 60us | 2us | 32us | +| Remove and Add a Component in ~1K entities | 15us | 25us | 12us | 240us | 8us | 136us | +| Remove and Add a Component in ~4K entities | 60us | 102us | 45us | 961us | 32us | 544us | +| Remove and Add a Component in ~16K entities | 244us | 453us | 183us | 3887us | 130us | 2172us | | | EntityX | EnTT | Ginseng | Flecs | pico_ecs | gaia-ecs | |:---------------------------------------------|:----------|:-------|:----------|:--------|:-----------|:-----------| -| Remove and Add a Component in ~65K entities | 0ms | 1ms | 0ms | 14ms | 0ms | 30ms | -| Remove and Add a Component in 262K entities | 3ms | 7ms | 3ms | 55ms | 2ms | 370ms | -| Remove and Add a Component in ~1M entities | 16ms | 29ms | 12ms | 222ms | 9ms | 5598ms | -| Remove and Add a Component in ~2M entities | 32ms | 58ms | 24ms | 445ms | 18ms | 23806ms | +| Remove and Add a Component in ~65K entities | 0ms | 1ms | 0ms | 15ms | 0ms | 8ms | +| Remove and Add a Component in 262K entities | 3ms | 6ms | 2ms | 61ms | 2ms | 34ms | +| Remove and Add a Component in ~1M entities | 15ms | 26ms | 11ms | 245ms | 8ms | 141ms | +| Remove and Add a Component in ~2M entities | 31ms | 52ms | 23ms | 489ms | 16ms | 279ms | @@ -333,24 +347,26 @@ _Tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Update 8 entities with 2 systems | 190ns | 92ns | 64ns | 13970ns | 1057ns | 67ns | 93ns | -| Update 16 entities with 2 systems | 369ns | 164ns | 115ns | 14232ns | 1078ns | 136ns | 122ns | -| Update 32 entities with 2 systems | 698ns | 293ns | 226ns | 14093ns | 1119ns | 248ns | 171ns | -| Update 64 entities with 2 systems | 1348ns | 564ns | 443ns | 14684ns | 1225ns | 472ns | 278ns | +| Update 1 entities with 2 systems | 39ns | 27ns | 13ns | 66ns | 1292ns | 20ns | 84ns | +| Update 4 entities with 2 systems | 93ns | 60ns | 34ns | 79ns | 1298ns | 39ns | 100ns | +| Update 8 entities with 2 systems | 166ns | 97ns | 59ns | 95ns | 1307ns | 65ns | 118ns | +| Update 16 entities with 2 systems | 315ns | 159ns | 109ns | 123ns | 1349ns | 132ns | 148ns | +| Update 32 entities with 2 systems | 649ns | 296ns | 216ns | 174ns | 1382ns | 241ns | 199ns | +| Update 64 entities with 2 systems | 1167ns | 561ns | 423ns | 286ns | 1511ns | 459ns | 308ns | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Update 256 entities with 2 systems | 5us | 2us | 1us | 15us | 1us | 1us | 0us | -| Update ~1K entities with 2 systems | 23us | 8us | 8us | 17us | 4us | 9us | 3us | -| Update ~4K entities with 2 systems | 86us | 35us | 27us | 26us | 15us | 28us | 15us | -| Update ~16K entities with 2 systems | 383us | 140us | 118us | 61us | 56us | 162us | 67us | +| Update 256 entities with 2 systems | 4us | 2us | 1us | 0us | 2us | 1us | 0us | +| Update ~1K entities with 2 systems | 20us | 8us | 8us | 3us | 4us | 7us | 3us | +| Update ~4K entities with 2 systems | 73us | 34us | 31us | 13us | 15us | 29us | 16us | +| Update ~16K entities with 2 systems | 314us | 143us | 127us | 54us | 56us | 115us | 66us | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| | Update ~65K entities with 2 systems | 1ms | 0ms | 0ms | 0ms | 0ms | 0ms | 0ms | | Update 262K entities with 2 systems | 5ms | 2ms | 2ms | 1ms | 3ms | 2ms | 3ms | -| Update ~1M entities with 2 systems | 24ms | 12ms | 11ms | 7ms | 13ms | 10ms | 13ms | -| Update ~2M entities with 2 systems | 54ms | 25ms | 22ms | 14ms | 26ms | 22ms | 26ms | +| Update ~1M entities with 2 systems | 21ms | 12ms | 11ms | 8ms | 13ms | 10ms | 13ms | +| Update ~2M entities with 2 systems | 44ms | 25ms | 23ms | 16ms | 25ms | 22ms | 27ms | @@ -372,24 +388,26 @@ _Tables shows total cost. lower is faster._ | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Update 8 entities with 2 systems | 158ns | 77ns | 54ns | 15284ns | 1117ns | 52ns | 124ns | -| Update 16 entities with 2 systems | 294ns | 140ns | 98ns | 15306ns | 1157ns | 89ns | 137ns | -| Update 32 entities with 2 systems | 589ns | 276ns | 195ns | 15313ns | 1206ns | 182ns | 189ns | -| Update 64 entities with 2 systems | 1153ns | 539ns | 410ns | 15377ns | 1292ns | 330ns | 290ns | +| Update 1 entities with 2 systems | 31ns | 16ns | 7ns | 36ns | 532ns | 14ns | 42ns | +| Update 4 entities with 2 systems | 75ns | 44ns | 28ns | 123ns | 1458ns | 33ns | 114ns | +| Update 8 entities with 2 systems | 139ns | 77ns | 51ns | 154ns | 1472ns | 53ns | 148ns | +| Update 16 entities with 2 systems | 271ns | 140ns | 93ns | 183ns | 1500ns | 88ns | 147ns | +| Update 32 entities with 2 systems | 537ns | 275ns | 196ns | 251ns | 1543ns | 180ns | 204ns | +| Update 64 entities with 2 systems | 1094ns | 538ns | 400ns | 338ns | 1650ns | 329ns | 315ns | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| -| Update 256 entities with 2 systems | 5us | 2us | 1us | 15us | 1us | 1us | 1us | -| Update ~1K entities with 2 systems | 20us | 8us | 6us | 19us | 4us | 7us | 3us | -| Update ~4K entities with 2 systems | 87us | 39us | 27us | 27us | 14us | 28us | 16us | -| Update ~16K entities with 2 systems | 403us | 134us | 132us | 63us | 57us | 152us | 67us | +| Update 256 entities with 2 systems | 4us | 2us | 1us | 1us | 2us | 1us | 1us | +| Update ~1K entities with 2 systems | 18us | 8us | 6us | 3us | 4us | 7us | 4us | +| Update ~4K entities with 2 systems | 73us | 32us | 26us | 14us | 15us | 36us | 16us | +| Update ~16K entities with 2 systems | 345us | 131us | 127us | 55us | 56us | 166us | 67us | | | EntityX | EnTT | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | |:-------------------------------------|:----------|:-------|:----------|:-----------|:--------|:-----------|:-----------| | Update ~65K entities with 2 systems | 1ms | 0ms | 0ms | 0ms | 0ms | 0ms | 0ms | -| Update 262K entities with 2 systems | 5ms | 2ms | 2ms | 1ms | 2ms | 2ms | 3ms | -| Update ~1M entities with 2 systems | 24ms | 14ms | 11ms | 7ms | 13ms | 11ms | 13ms | -| Update ~2M entities with 2 systems | 51ms | 26ms | 22ms | 14ms | 26ms | 23ms | 27ms | +| Update 262K entities with 2 systems | 5ms | 3ms | 2ms | 2ms | 2ms | 2ms | 3ms | +| Update ~1M entities with 2 systems | 21ms | 14ms | 11ms | 7ms | 13ms | 11ms | 13ms | +| Update ~2M entities with 2 systems | 44ms | 29ms | 23ms | 15ms | 26ms | 23ms | 27ms | **Note:** @@ -410,25 +428,27 @@ _Tables shows total cost. lower is faster._ _Tables shows total cost. lower is faster._ | | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| -| Update 8 entities with 7 systems | 452ns | 977ns | 254ns | 331ns | 233ns | 50924ns | 2110ns | 248ns | 333ns | 340ns | -| Update 16 entities with 7 systems | 784ns | 1865ns | 399ns | 520ns | 464ns | 50202ns | 2169ns | 433ns | 421ns | 436ns | -| Update 32 entities with 7 systems | 1312ns | 3569ns | 701ns | 1046ns | 1055ns | 50993ns | 2317ns | 783ns | 576ns | 576ns | -| Update 64 entities with 7 systems | 2501ns | 6952ns | 1362ns | 2044ns | 1661ns | 51462ns | 2613ns | 1481ns | 888ns | 931ns | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update 1 entities with 7 systems | 136ns | 173ns | 100ns | 133ns | 51ns | 223ns | 2930ns | 64ns | 290ns | 280ns | +| Update 4 entities with 7 systems | 301ns | 504ns | 181ns | 216ns | 119ns | 273ns | 2948ns | 132ns | 326ns | 318ns | +| Update 8 entities with 7 systems | 463ns | 960ns | 254ns | 316ns | 201ns | 325ns | 2958ns | 243ns | 375ns | 361ns | +| Update 16 entities with 7 systems | 727ns | 1813ns | 429ns | 527ns | 392ns | 398ns | 3040ns | 439ns | 465ns | 449ns | +| Update 32 entities with 7 systems | 1332ns | 3574ns | 723ns | 999ns | 728ns | 536ns | 3174ns | 788ns | 615ns | 606ns | +| Update 64 entities with 7 systems | 2655ns | 7155ns | 1388ns | 2257ns | 1348ns | 833ns | 3492ns | 1482ns | 956ns | 943ns | | | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| -| Update 256 entities with 7 systems | 10us | 27us | 6us | 9us | 5us | 52us | 4us | 5us | 3us | 3us | -| Update ~1K entities with 7 systems | 46us | 116us | 28us | 39us | 22us | 57us | 10us | 22us | 14us | 15us | -| Update ~4K entities with 7 systems | 188us | 478us | 142us | 162us | 99us | 83us | 38us | 100us | 72us | 73us | -| Update ~16K entities with 7 systems | 816us | 1882us | 569us | 646us | 424us | 198us | 202us | 405us | 351us | 323us | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update 256 entities with 7 systems | 11us | 29us | 6us | 9us | 5us | 2us | 5us | 6us | 3us | 3us | +| Update ~1K entities with 7 systems | 48us | 116us | 30us | 38us | 21us | 8us | 11us | 22us | 14us | 13us | +| Update ~4K entities with 7 systems | 200us | 481us | 154us | 164us | 93us | 39us | 38us | 92us | 72us | 71us | +| Update ~16K entities with 7 systems | 830us | 1990us | 606us | 648us | 371us | 182us | 173us | 407us | 341us | 346us | | | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| -| Update ~65K entities with 7 systems | 3ms | 7ms | 2ms | 2ms | 1ms | 0ms | 0ms | 1ms | 1ms | 1ms | -| Update 262K entities with 7 systems | 14ms | 31ms | 11ms | 11ms | 8ms | 4ms | 6ms | 7ms | 10ms | 11ms | -| Update ~1M entities with 7 systems | 57ms | 121ms | 51ms | 45ms | 35ms | 16ms | 22ms | 29ms | 44ms | 43ms | -| Update ~2M entities with 7 systems | 112ms | 233ms | 124ms | 89ms | 71ms | 38ms | 49ms | 60ms | 86ms | 90ms | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update ~65K entities with 7 systems | 3ms | 7ms | 2ms | 2ms | 1ms | 0ms | 0ms | 1ms | 1ms | 1ms | +| Update 262K entities with 7 systems | 14ms | 32ms | 11ms | 11ms | 7ms | 4ms | 5ms | 7ms | 10ms | 10ms | +| Update ~1M entities with 7 systems | 58ms | 123ms | 52ms | 45ms | 30ms | 17ms | 21ms | 29ms | 43ms | 42ms | +| Update ~2M entities with 7 systems | 113ms | 233ms | 122ms | 90ms | 59ms | 42ms | 44ms | 61ms | 85ms | 85ms | @@ -463,25 +483,27 @@ _Tables shows total cost. lower is faster._ _Tables shows total cost. lower is faster._ | | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| -| Update 8 entities with 7 Systems | 355ns | 693ns | 199ns | 253ns | 169ns | 53373ns | 2332ns | 176ns | 390ns | 393ns | -| Update 16 entities with 7 Systems | 360ns | 834ns | 184ns | 176ns | 210ns | 51544ns | 2198ns | 181ns | 315ns | 335ns | -| Update 32 entities with 7 Systems | 595ns | 1576ns | 286ns | 230ns | 383ns | 52746ns | 2266ns | 323ns | 382ns | 389ns | -| Update 64 entities with 7 Systems | 1052ns | 2961ns | 476ns | 343ns | 720ns | 51403ns | 2402ns | 559ns | 518ns | 518ns | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update 1 entities with 7 Systems | 124ns | 135ns | 78ns | 128ns | 41ns | 240ns | 1921ns | 65ns | 222ns | 231ns | +| Update 4 entities with 7 Systems | 212ns | 345ns | 126ns | 179ns | 115ns | 460ns | 3347ns | 122ns | 410ns | 392ns | +| Update 8 entities with 7 Systems | 334ns | 632ns | 181ns | 255ns | 165ns | 521ns | 3452ns | 179ns | 455ns | 454ns | +| Update 16 entities with 7 Systems | 332ns | 835ns | 177ns | 181ns | 220ns | 474ns | 3187ns | 190ns | 356ns | 349ns | +| Update 32 entities with 7 Systems | 559ns | 1618ns | 268ns | 235ns | 370ns | 545ns | 3231ns | 326ns | 425ns | 416ns | +| Update 64 entities with 7 Systems | 1028ns | 3067ns | 471ns | 346ns | 712ns | 674ns | 3399ns | 563ns | 568ns | 571ns | | | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| -| Update 256 entities with 7 Systems | 7us | 21us | 4us | 4us | 4us | 52us | 3us | 4us | 2us | 2us | -| Update ~1K entities with 7 Systems | 34us | 84us | 18us | 21us | 16us | 64us | 9us | 18us | 10us | 10us | -| Update ~4K entities with 7 Systems | 137us | 347us | 92us | 89us | 68us | 86us | 29us | 75us | 44us | 46us | -| Update ~16K entities with 7 Systems | 550us | 1385us | 391us | 356us | 296us | 181us | 124us | 329us | 218us | 215us | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update 256 entities with 7 Systems | 7us | 21us | 3us | 4us | 4us | 2us | 4us | 4us | 2us | 2us | +| Update ~1K entities with 7 Systems | 31us | 87us | 18us | 21us | 16us | 7us | 10us | 17us | 10us | 9us | +| Update ~4K entities with 7 Systems | 140us | 355us | 93us | 89us | 70us | 28us | 32us | 80us | 45us | 46us | +| Update ~16K entities with 7 Systems | 576us | 1439us | 407us | 352us | 297us | 122us | 116us | 310us | 215us | 216us | | | EnTT | EnTT (runtime) | EnTT (group) | EnTT (stable) | Ginseng | mustache | Flecs | pico_ecs | gaia-ecs | gaia-ecs (SoA) | -|:-------------------------------------|:-------|:-----------------|:---------------|:----------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| -| Update ~65K entities with 7 Systems | 2ms | 5ms | 1ms | 1ms | 1ms | 0ms | 0ms | 1ms | 1ms | 1ms | -| Update 262K entities with 7 Systems | 10ms | 23ms | 8ms | 6ms | 6ms | 3ms | 3ms | 6ms | 7ms | 8ms | -| Update ~1M entities with 7 Systems | 40ms | 92ms | 36ms | 26ms | 27ms | 14ms | 19ms | 23ms | 32ms | 32ms | -| Update ~2M entities with 7 Systems | 82ms | 176ms | 88ms | 53ms | 55ms | 27ms | 37ms | 47ms | 65ms | 65ms | +|:-------------------------------------|:-------|:-----------------|:---------------|:----------------------|:----------|:-----------|:--------|:-----------|:-----------|:-----------------| +| Update ~65K entities with 7 Systems | 2ms | 5ms | 1ms | 1ms | 1ms | 0ms | 0ms | 1ms | 1ms | 1ms | +| Update 262K entities with 7 Systems | 10ms | 24ms | 8ms | 6ms | 6ms | 3ms | 4ms | 5ms | 7ms | 7ms | +| Update ~1M entities with 7 Systems | 41ms | 95ms | 35ms | 26ms | 27ms | 16ms | 20ms | 23ms | 31ms | 31ms | +| Update ~2M entities with 7 Systems | 84ms | 183ms | 86ms | 52ms | 54ms | 32ms | 38ms | 49ms | 62ms | 65ms | @@ -563,6 +585,17 @@ task generate:readme 2. `pipx run --spec ./scripts/gen-benchmark-report gen-benchmark-report -i ./info.json gen-results-md ./reports/entityx.json ./reports/entt.json ./reports/ginseng.json ./reports/mustache.json ./reports/openecs.json ./reports/flecs.json` _(generate full report)_ +### Run a single benchmark + +```bash +cmake -G Ninja -S . -B build +cmake --build build --target ecs-benchmark-entt -j 4 +./build/benchmark/benchmarks/entt/ecs-benchmark-entt +``` + +You can use `-DCMAKE_BUILD_TYPE=Debug` to enable Sanitizers. + + ## Links and More - [Dependency Setup](doc/README_dependencies.md) @@ -586,7 +619,7 @@ Version: 1.1.2 (Apr 2023) > EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++. -Version: v3.13.1 +Version: v3.13.2 #### Ginseng by @apples @@ -614,7 +647,7 @@ Version: 0.1.101 (Apr 2017) > Flecs is a fast and lightweight Entity Component System that lets you build games and simulations with millions of entities. -Version: v3.2.11 +Version: v4.0.0 #### pico_ecs by @empyreanx @@ -626,5 +659,5 @@ Version: 2.3 (Sep 2023) > Gaia-ECS is a fast and easy-to-use ECS framework. -Version: v0.8.4 +Version: v0.8.6 diff --git a/README.md.mustache b/README.md.mustache index 2f13796..a27d6a8 100644 --- a/README.md.mustache +++ b/README.md.mustache @@ -277,6 +277,17 @@ task generate:readme 2. `pipx run --spec ./scripts/gen-benchmark-report gen-benchmark-report -i ./info.json gen-results-md ./reports/entityx.json ./reports/entt.json ./reports/ginseng.json ./reports/mustache.json ./reports/openecs.json ./reports/flecs.json` _(generate full report)_ +### Run a single benchmark + +```bash +cmake -G Ninja -S . -B build +cmake --build build --target ecs-benchmark-entt -j 4 +./build/benchmark/benchmarks/entt/ecs-benchmark-entt +``` + +You can use `-DCMAKE_BUILD_TYPE=Debug` to enable Sanitizers. + + ## Links and More - [Dependency Setup](doc/README_dependencies.md) diff --git a/benchmark/benchmarks/ECSBenchmark.h b/benchmark/benchmarks/ECSBenchmark.h index 60b189a..28d764c 100644 --- a/benchmark/benchmarks/ECSBenchmark.h +++ b/benchmark/benchmarks/ECSBenchmark.h @@ -53,20 +53,6 @@ class ECSBenchmark : protected BaseECSBenchmark { [[nodiscard]] inline const char* name() const noexcept { return m_name; } [[nodiscard]] inline auto framework_version() const { return m_options.version; } - - void BM_SystemsUpdate_NoEntities(benchmark::State& state) { - // const auto nentities = 0; - std::vector entities; - Application app(m_options.add_more_complex_system); - const ComponentsCounter components_counter = this->initApplicationWithoutEntities(app); - for (auto _ : state) { - app.update(fakeTimeDelta); - } - this->setCounters(state, entities, components_counter); - afterBenchmark(app); - uninitApplication(app); - } - void BM_SystemsUpdate(benchmark::State& state) { const auto nentities = static_cast(state.range(0)); std::vector entities; @@ -295,25 +281,6 @@ class ECSBenchmark : protected BaseECSBenchmark { this->setCounters(state, entities, components_counter); } - template - 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); - EntityManager& registry = app.getEntities(); - std::vector entities; - const ComponentsCounter components_counter = - this->createEntitiesWithMinimalComponents(registry, nentities, entities); - - for (auto _ : state) { - for (auto& entity : entities) { - benchmark::DoNotOptimize(this->m_entities_factory.getComponentOne(registry, entity)); - } - } - this->setCounters(state, entities, components_counter); - } - template requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes && HasGetComponentsFeature) @@ -410,6 +377,27 @@ class ECSBenchmark : protected BaseECSBenchmark { this->setCounters(state, entities, components_counter); } + template + requires(include_entity_benchmarks == ECSBenchmarkIncludeEntityBenchmarks::Yes) + void BM_AddComponent(benchmark::State& state) { + const auto nentities = static_cast(state.range(0)); + Application app(m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const ComponentsCounter components_counter = + this->createEntitiesWithMinimalComponents(registry, nentities, entities); + + for (auto _ : state) { + for (auto& entity : entities) { + state.PauseTiming(); + this->m_entities_factory.removeComponentOne(registry, entity); + state.ResumeTiming(); + this->m_entities_factory.addComponentOne(registry, entity); + } + } + this->setCounters(state, entities, components_counter); + } + protected: ComponentsCounter initApplicationWithoutEntities(Application& app) { app.init(); @@ -490,10 +478,6 @@ class ECSBenchmark : protected BaseECSBenchmark { } // namespace ecs::benchmarks::base #define ECS_UPDATE_SYSTEMS_BENCHMARKS(benchmark_suite) \ - static void BM_SystemsUpdate_NoEntities(benchmark::State& state) { \ - benchmark_suite.BM_SystemsUpdate_NoEntities(state); \ - } \ - BENCHMARK(BM_SystemsUpdate_NoEntities); \ static void BM_SystemsUpdate(benchmark::State& state) { \ benchmark_suite.BM_SystemsUpdate(state); \ } \ @@ -505,10 +489,6 @@ class ECSBenchmark : protected BaseECSBenchmark { #define ECS_COMPLEX_UPDATE_SYSTEMS_BENCHMARKS(benchmark_suite) \ - static void BM_ComplexSystemsUpdate_NoEntities(benchmark::State& state) { \ - benchmark_suite.BM_SystemsUpdate_NoEntities(state); \ - } \ - BENCHMARK(BM_ComplexSystemsUpdate_NoEntities); \ static void BM_ComplexSystemsUpdate(benchmark::State& state) { \ benchmark_suite.BM_SystemsUpdate(state); \ } \ diff --git a/benchmark/benchmarks/EntityBenchmark.h b/benchmark/benchmarks/EntityBenchmark.h index d200673..94a4e49 100644 --- a/benchmark/benchmarks/EntityBenchmark.h +++ b/benchmark/benchmarks/EntityBenchmark.h @@ -75,6 +75,11 @@ concept HasGetConstComponentsThreeFeature = factory.getComponentTwoConst(entity_manager, entity); factory.getOptionalComponentThreeConst(entity_manager, entity); }; +template +concept HasAddComponentThreeFeature = requires(EntityFactory factory, EntityManager& entity_manager, Entity entity) { + factory.addComponentEmpty(entity_manager, entity); +}; template requires std::default_initializable @@ -286,34 +291,6 @@ class EntityBenchmark : public BaseECSBenchmark { }); } - template - requires HasGetComponentsFeature || HasGetConstComponentsFeature - void BM_UnpackOneComponent_NoEntities(benchmark::State& state) { - const auto nentities = 0; - EntityManager registry; - std::vector entities; - const ComponentsCounter components_counter = - this->createEntitiesWithMinimalComponents(registry, nentities, entities); - - constexpr bool hasOnlyGetConstComponentsFeature = - !HasGetComponentsFeature || HasGetConstComponentsFeature; - - for (auto _ : state) { - for (auto& entity : entities) { - if constexpr (hasOnlyGetConstComponentsFeature) { - auto c = this->m_entities_factory.getComponentOneConst(registry, entity); - benchmark::DoNotOptimize(c); - } else { - // benchmark::DoNotOptimize(this->m_entities_factory.getComponentOne(registry, entity)); - // to be fair - auto c = this->m_entities_factory.getComponentOne(registry, entity); - benchmark::DoNotOptimize(c); - } - } - } - this->setCounters(state, entities, components_counter); - } - template requires HasGetComponentsFeature || HasGetConstComponentsFeature void BM_UnpackOneComponent(benchmark::State& state) { @@ -428,6 +405,24 @@ class EntityBenchmark : public BaseECSBenchmark { this->setCounters(state, entities, components_counter); } + void BM_AddComponent(benchmark::State& state) { + const auto nentities = static_cast(state.range(0)); + EntityManager registry; + std::vector entities; + const ComponentsCounter components_counter = + this->createEntitiesWithMinimalComponents(registry, nentities, entities); + + for (auto _ : state) { + for (auto& entity : entities) { + state.PauseTiming(); + this->m_entities_factory.removeComponentOne(registry, entity); + state.ResumeTiming(); + this->m_entities_factory.addComponentOne(registry, entity); + } + } + this->setCounters(state, entities, components_counter); + } + protected: inline static constexpr auto m_name{Name.value}; const ESCBenchmarkOptions m_options; @@ -455,10 +450,6 @@ class EntityBenchmark : public BaseECSBenchmark { benchmark_suite.BM_UnpackOneComponent(state); \ } \ BENCHMARK(BM_UnpackOneComponent)->Apply(ecs::benchmarks::base::BEDefaultArguments); \ - static void BM_UnpackOneComponent_NoEntities(benchmark::State& state) { \ - benchmark_suite.BM_UnpackOneComponent_NoEntities(state); \ - } \ - BENCHMARK(BM_UnpackOneComponent_NoEntities); \ static void BM_UnpackTwoComponents(benchmark::State& state) { \ benchmark_suite.BM_UnpackTwoComponents(state); \ } \ @@ -469,6 +460,10 @@ class EntityBenchmark : public BaseECSBenchmark { BENCHMARK(BM_UnpackThreeComponents)->Apply(ecs::benchmarks::base::BEDefaultArguments); #define ECS_REMOVE_ENTITY_BENCHMARKS(benchmark_suite) \ + static void BM_AddComponent(benchmark::State& state) { \ + benchmark_suite.BM_AddComponent(state); \ + } \ + BENCHMARK(BM_AddComponent)->Apply(ecs::benchmarks::base::BEDefaultArguments); \ static void BM_RemoveAddComponent(benchmark::State& state) { \ benchmark_suite.BM_RemoveAddComponent(state); \ } \ diff --git a/benchmark/benchmarks/ExtendedECSBenchmark.h b/benchmark/benchmarks/ExtendedECSBenchmark.h index f975ef7..5bd5e28 100644 --- a/benchmark/benchmarks/ExtendedECSBenchmark.h +++ b/benchmark/benchmarks/ExtendedECSBenchmark.h @@ -14,6 +14,17 @@ concept HasForEach = requires(Iterable it, Func func) { it.for_each(func); }; template concept HasVisit = requires(Iterable it, Func func) { it.visit(func); }; +template +concept HasClearComponentFeature = requires(EntityFactory factory, EntityManager& entity_manager, Entity entity) { + factory.clearComponentsEmpty(entity_manager); +}; +template +concept HasAddComponentEmptyFeature = requires(EntityFactory factory, EntityManager& entity_manager, Entity entity) { + factory.addComponentEmpty(entity_manager, entity); +}; + template class ExtendedECSBenchmark @@ -397,11 +408,121 @@ class ExtendedECSBenchmark } + template + requires std::invocable && HasClearComponentFeature + void BM_PublishEventsViaComponentWithMixedEntitiesCustom(benchmark::State& state, GetViewWithRegistry&& get_view_with_registry, + PublishEventFunc&& event_func) { + const auto nentities = static_cast(state.range(0)); + if constexpr (default_initializable_entity_manager) { + EntityManager registry; + std::vector entities; + const ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + auto view = get_view_with_registry(registry); + for (auto _ : state) { + event_func(registry, view); + this->m_entities_factory.clearComponentsEmpty(registry); + } + + this->setCounters(state, entities, components_counter); + } else { + Application app(this->m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const ComponentsCounter components_counter = + this->createEntitiesWithMinimalComponents(registry, nentities, entities); + + auto view = get_view_with_registry(registry); + for (auto _ : state) { + event_func(registry, view); + this->m_entities_factory.clearComponentsEmpty(registry); + } + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } + } + template + requires std::invocable && HasClearComponentFeature + void BM_PublishEventsViaComponentWithMixedEntitiesViews(benchmark::State& state, GetViewWithRegistry&& get_view_with_registry, PublishEventFunc&& event_func) { + BM_PublishEventsViaComponentWithMixedEntitiesCustom(state, get_view_with_registry, [&](auto& registry, auto& view) { + generic_each(view, [&](auto&&... comps){ event_func(std::forward(registry), std::forward(comps)...); }); + }); + } + template + requires std::invocable && HasClearComponentFeature && HasAddComponentEmptyFeature + void BM_PublishEventsViaComponentWithMixedEntitiesViews(benchmark::State& state, GetViewWithRegistry&& get_view_with_registry) { + BM_PublishEventsViaComponentWithMixedEntitiesViews(state, get_view_with_registry, [&](auto& registry, auto entity, auto&... /*comps*/) { + this->m_entities_factory.addComponentEmpty(registry, entity); + }); + } + + template + requires std::invocable && std::invocable && HasClearComponentFeature + void BM_PublishAndUpdateEventsViaComponentWithMixedEntitiesCustom(benchmark::State& state, GetViewWithRegistry&& get_view_with_registry, GetViewWithEvent&& get_view_with_event, + PublishEventFunc&& event_func, UpdateFunc&& update_func) { + const auto nentities = static_cast(state.range(0)); + if constexpr (default_initializable_entity_manager) { + EntityManager registry; + std::vector entities; + const ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + auto view = get_view_with_registry(registry); + auto event_view = get_view_with_event(registry); + for (auto _ : state) { + update_func(registry, view); + event_func(registry, event_view); + this->m_entities_factory.clearComponentsEmpty(registry); + } + + this->setCounters(state, entities, components_counter); + } else { + Application app(this->m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const ComponentsCounter components_counter = + this->createEntitiesWithMinimalComponents(registry, nentities, entities); + + auto view = get_view_with_registry(registry); + auto event_view = get_view_with_event(registry); + for (auto _ : state) { + update_func(registry, view); + event_func(registry, event_view); + this->m_entities_factory.clearComponentsEmpty(registry); + } + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } + } + template + requires std::invocable && std::invocable && HasClearComponentFeature + void BM_PublishAndUpdateEventsViaComponentWithMixedEntitiesViews(benchmark::State& state, GetViewWithRegistry&& get_view_with_registry, GetViewWithEvent&& get_view_with_event, PublishEventFunc&& event_func, UpdateFunc&& update_func) { + BM_PublishAndUpdateEventsViaComponentWithMixedEntitiesCustom(state, get_view_with_registry, get_view_with_event, [&](auto& registry, auto& view) { + generic_each(view, [&](auto&&... comps){ event_func(std::forward(registry), std::forward(comps)...); }); + }, [&](auto& /*registry*/, auto& view) { + generic_each(view, update_func); + }); + } + template + requires std::invocable && std::invocable && HasClearComponentFeature && HasAddComponentEmptyFeature + void BM_PublishAndUpdateEventsViaComponentWithMixedEntitiesViews(benchmark::State& state, GetViewWithRegistry&& get_view_with_registry, GetViewWithEvent&& get_view_with_event) { + BM_PublishAndUpdateEventsViaComponentWithMixedEntitiesViews(state, get_view_with_registry, get_view_with_event, [&](auto& registry, auto entity, auto&... /*comps*/) { + this->m_entities_factory.addComponentEmpty(registry, entity); + }, [](auto& /*entity*/, auto&... comp) { + dummy_each(comp...); + }); + } + + public: template - inline static void dummy_each(Comp& comp, Args&&... args) { - benchmark::DoNotOptimize(comp); - (benchmark::DoNotOptimize(args), ...); + inline static void dummy_each(Comp& comp_or_entity, Args&... comps) { + benchmark::DoNotOptimize(comp_or_entity); + (benchmark::DoNotOptimize(comps), ...); + //assert(comp_or_entity); } template diff --git a/benchmark/benchmarks/basic.cpp b/benchmark/benchmarks/basic.cpp index a0f5dd8..3d84a38 100644 --- a/benchmark/benchmarks/basic.cpp +++ b/benchmark/benchmarks/basic.cpp @@ -8,4 +8,10 @@ void BEDefaultArguments(benchmark::internal::Benchmark* b) { }); } +void BESmallArguments(benchmark::internal::Benchmark* b) { + b->ArgsProduct({ + benchmark::CreateRange(MIN_ENTITIES_RANGE, SMALL_MAX_ENTITIES_RANGE, /*multi=*/2), + }); +} + } // namespace ecs::benchmarks::base \ No newline at end of file diff --git a/benchmark/benchmarks/basic.h b/benchmark/benchmarks/basic.h index 83792ae..41318a0 100644 --- a/benchmark/benchmarks/basic.h +++ b/benchmark/benchmarks/basic.h @@ -35,10 +35,13 @@ struct ComponentsCounter { size_t monster_count{0}; }; -inline static constexpr auto MIN_ENTITIES_RANGE = 8L; +inline static constexpr auto MIN_ENTITIES_RANGE = 0L; inline static constexpr auto MAX_ENTITIES_RANGE = 2'097'152L; +inline static constexpr auto SMALL_MAX_ENTITIES_RANGE = 32'768L; void BEDefaultArguments(benchmark::internal::Benchmark* b); +void BESmallArguments(benchmark::internal::Benchmark* b); + } // namespace ecs::benchmarks::base #endif // ECS_BENCHMARKS_BASICBENCHMARK_H_ diff --git a/benchmark/benchmarks/entt-extended/CMakeLists.txt b/benchmark/benchmarks/entt-extended/CMakeLists.txt index 3b0a193..af410f8 100755 --- a/benchmark/benchmarks/entt-extended/CMakeLists.txt +++ b/benchmark/benchmarks/entt-extended/CMakeLists.txt @@ -10,10 +10,73 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended PRIVATE ecs-benchmark-example-entt) + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-entt-extended-event + # NOTE: add new benchmarks here + EnttEventBenchmarkSuite.cpp EnttEventBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-entt-extended-event + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-entt-extended-event PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-entt-extended-event PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-entt-extended-event PRIVATE ecs-benchmark-example-entt) + + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-entt-extended-event-emit + # NOTE: add new benchmarks here + EnttEventEmitBenchmarkSuite.cpp EnttEventEmitBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-entt-extended-event-emit + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-entt-extended-event-emit PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-entt-extended-event-emit PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-entt-extended-event-emit PRIVATE ecs-benchmark-example-entt) + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-entt-extended-event-emit-stable + # NOTE: add new benchmarks here + EnttStableEventEmitBenchmarkSuite.cpp EnttStableEventEmitBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-entt-extended-event-emit-stable + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-entt-extended-event-emit-stable PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-entt-extended-event-emit-stable PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-entt-extended-event-emit-stable PRIVATE ecs-benchmark-example-entt) + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-entt-extended-event-comp + # NOTE: add new benchmarks here + EnttEventComponentBenchmarkSuite.cpp EnttEventComponentBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-entt-extended-event-comp + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-entt-extended-event-comp PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-entt-extended-event-comp PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-entt-extended-event-comp PRIVATE ecs-benchmark-example-entt) + + + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "ecs-benchmark-myecs" add_executable( @@ -26,10 +89,10 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended-stable PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended-stable PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended-stable PRIVATE ecs-benchmark-example-entt) + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "ecs-benchmark-myecs" add_executable( @@ -42,10 +105,10 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended-runtime PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended-runtime PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended-runtime PRIVATE ecs-benchmark-example-entt) + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "ecs-benchmark-myecs" add_executable( @@ -58,10 +121,10 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended-group PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended-group PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended-group PRIVATE ecs-benchmark-example-entt) + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "ecs-benchmark-myecs" add_executable( @@ -74,10 +137,10 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended-non-owning-group PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended-non-owning-group PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended-non-owning-group PRIVATE ecs-benchmark-example-entt) + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "ecs-benchmark-myecs" add_executable( @@ -90,10 +153,10 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended-full-owning-group PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended-full-owning-group PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended-full-owning-group PRIVATE ecs-benchmark-example-entt) + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "ecs-benchmark-myecs" add_executable( @@ -106,6 +169,5 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-entt-extended-partial-owning-group PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-entt-extended-partial-owning-group PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-entt-extended-partial-owning-group PRIVATE ecs-benchmark-example-entt) diff --git a/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.cpp b/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.cpp index 8c932a4..1fe9ba2 100644 --- a/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.cpp +++ b/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.cpp @@ -6,3 +6,4 @@ static ecs::benchmarks::entt::EnttBenchmarkSuite ECS_COMPLEX_UPDATE_SYSTEMS_BENCHMARKS(benchmark_suite) ECS_ITERATE_COMPONENTS_BENCHMARKS(benchmark_suite) + diff --git a/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h index 01c5106..9a69e37 100644 --- a/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h +++ b/benchmark/benchmarks/entt-extended/EnttBenchmarkSuite.h @@ -9,6 +9,11 @@ namespace ecs::benchmarks::entt { +template +struct DummyListener { + void receive(Event& event) { benchmark::DoNotOptimize(event); } +}; + class EnttBenchmarkSuite final : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt", EnttApplication, entities::EntityFactory, entities::HeroMonsterEntityFactory> { diff --git a/benchmark/benchmarks/entt-extended/EnttEventBenchmarkSuite.cpp b/benchmark/benchmarks/entt-extended/EnttEventBenchmarkSuite.cpp new file mode 100644 index 0000000..243da14 --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttEventBenchmarkSuite.cpp @@ -0,0 +1,20 @@ +#include "EnttEventBenchmarkSuite.h" + +static ecs::benchmarks::entt::EnttEventBenchmarkSuite + benchmark_suite({.add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = ENTT_VERSION}); + +static void BM_EnqueueAndUpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_EnqueueAndUpdateEventsViaDispatcherWithMixedEntities(state); +} +BENCHMARK(BM_EnqueueAndUpdateEventsViaDispatcherWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); + +static void BM_EnqueueEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_EnqueueEventsViaDispatcherWithMixedEntities(state); +} +BENCHMARK(BM_EnqueueEventsViaDispatcherWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); + +static void BM_UpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_UpdateEventsViaDispatcherWithMixedEntities(state); +} +BENCHMARK(BM_UpdateEventsViaDispatcherWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); diff --git a/benchmark/benchmarks/entt-extended/EnttEventBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttEventBenchmarkSuite.h new file mode 100644 index 0000000..8634280 --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttEventBenchmarkSuite.h @@ -0,0 +1,156 @@ +#ifndef ECS_BENCHMARKS_ENTTBENCHMARK_H_ +#define ECS_BENCHMARKS_ENTTBENCHMARK_H_ + +#include "ExtendedECSBenchmark.h" +#include "entt/EnttApplication.h" +#include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::entt { + +struct Event { + ::entt::entity entity; +}; + +struct DummyListener { +public: + DummyListener(::entt::registry& registry, + ::entt::dispatcher& dispatcher) : m_registry(registry), m_dispatcher(dispatcher) {} + + void setup() { + m_dispatcher.sink().connect<&DummyListener::receive>(*this); + } + void teardown() { + m_dispatcher.sink().disconnect<&DummyListener::receive>(*this); + } + + void receive(Event& event) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + + auto& comp1 = m_registry.get(event.entity); + auto& comp2 = m_registry.get(event.entity); + + benchmark::DoNotOptimize(comp1); + benchmark::DoNotOptimize(comp2); + //benchmark::DoNotOptimize(event); + } + +private: + ::entt::registry& m_registry; + ::entt::dispatcher& m_dispatcher; +}; + +class EnttEventBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (event)", EnttApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { +public: + EnttEventBenchmarkSuite() = default; + + explicit EnttEventBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + void BM_EnqueueAndUpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + + const auto nentities = static_cast(state.range(0)); + EnttApplication::Application app(this->m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + ::entt::dispatcher dispatcher{}; + DummyListener listener (registry, dispatcher); + + listener.setup(); + + auto view = registry.template view(); + for (auto _ : state) { + view.each([&](auto entity, auto& /*comp1*/, auto& /*comp2*/) { + //dummy_each(comp1, comp2); + dispatcher.enqueue({.entity = entity}); + }); + dispatcher.update(); + //dispatcher.update(); + } + + listener.teardown(); + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } + + void BM_EnqueueEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + //using EventComponent = ecs::benchmarks::base::components::EmptyComponent; + + const auto nentities = static_cast(state.range(0)); + EnttApplication::Application app(this->m_options.add_more_complex_system); + ::entt::registry& registry = app.getEntities(); + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + ::entt::dispatcher dispatcher{}; + DummyListener listener (registry, dispatcher); + + listener.setup(); + + auto view = registry.template view(); + for (auto _ : state) { + view.each([&](auto entity, auto& /*comp1*/, auto& /*comp2*/) { + //dummy_each(comp1, comp2); + dispatcher.enqueue({.entity = entity}); + }); + } + //dispatcher.update(); + + listener.teardown(); + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } + + void BM_UpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + //using EventComponent = ecs::benchmarks::base::components::EmptyComponent; + + const auto nentities = static_cast(state.range(0)); + EnttApplication::Application app(this->m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + ::entt::dispatcher dispatcher{}; + DummyListener listener (registry, dispatcher); + + listener.setup(); + + auto view = registry.template view(); + view.each([&](auto entity, auto& /*comp1*/, auto& /*comp2*/) { + //dummy_each(comp1, comp2); + dispatcher.enqueue({.entity = entity}); + }); + state.counters["events_count"] = static_cast(dispatcher.size()); + + for (auto _ : state) { + dispatcher.update(); + //dispatcher.update(); + } + + listener.teardown(); + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } +}; + +} // namespace ecs::benchmarks::entt + +#endif // ECS_BENCHMARKS_ENTTBENCHMARK_H_ diff --git a/benchmark/benchmarks/entt-extended/EnttEventComponentBenchmarkSuite.cpp b/benchmark/benchmarks/entt-extended/EnttEventComponentBenchmarkSuite.cpp new file mode 100644 index 0000000..2c38ed2 --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttEventComponentBenchmarkSuite.cpp @@ -0,0 +1,15 @@ +#include "EnttEventComponentBenchmarkSuite.h" + +static ecs::benchmarks::entt::EnttEventComponentBenchmarkSuite + benchmark_suite({.add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = ENTT_VERSION}); + +static void BM_PublishAndUpdateEventsViaComponentWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_PublishAndUpdateEventsViaComponentWithMixedEntities(state); +} +BENCHMARK(BM_PublishAndUpdateEventsViaComponentWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); + +static void BM_PublishEventsViaComponentWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_PublishEventsViaComponentWithMixedEntities(state); +} +BENCHMARK(BM_PublishEventsViaComponentWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); diff --git a/benchmark/benchmarks/entt-extended/EnttEventComponentBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttEventComponentBenchmarkSuite.h new file mode 100644 index 0000000..72f9dce --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttEventComponentBenchmarkSuite.h @@ -0,0 +1,50 @@ +#ifndef ECS_BENCHMARKS_ENTTBENCHMARK_EVENTCOMP_H_ +#define ECS_BENCHMARKS_ENTTBENCHMARK_EVENTCOMP_H_ + +#include "ExtendedECSBenchmark.h" +#include "entt/EnttApplication.h" +#include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::entt { + +class EnttEventComponentBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (component)", EnttApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { +public: + EnttEventComponentBenchmarkSuite() = default; + + explicit EnttEventComponentBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + void BM_PublishEventsViaComponentWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + //using EventComponent = ecs::benchmarks::base::components::EmptyComponent; + + BM_PublishEventsViaComponentWithMixedEntitiesViews( + state, + [](auto& registry) { + return registry.template view(); + }); + } + void BM_PublishAndUpdateEventsViaComponentWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + using EventComponent = ecs::benchmarks::base::components::EmptyComponent; + + BM_PublishAndUpdateEventsViaComponentWithMixedEntitiesViews( + state, + [](auto& registry) { + return registry.template view(); + }, + [](auto& registry) { + return registry.template view(); + }); + } +}; + +} // namespace ecs::benchmarks::entt + +#endif // ECS_BENCHMARKS_ENTTBENCHMARK_H_ diff --git a/benchmark/benchmarks/entt-extended/EnttEventEmitBenchmarkSuite.cpp b/benchmark/benchmarks/entt-extended/EnttEventEmitBenchmarkSuite.cpp new file mode 100644 index 0000000..c4f8b0e --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttEventEmitBenchmarkSuite.cpp @@ -0,0 +1,10 @@ +#include "EnttEventEmitBenchmarkSuite.h" + +static ecs::benchmarks::entt::EnttEventEmitBenchmarkSuite + benchmark_suite({.add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = ENTT_VERSION}); + +static void BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities(state); +} +BENCHMARK(BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); diff --git a/benchmark/benchmarks/entt-extended/EnttEventEmitBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttEventEmitBenchmarkSuite.h new file mode 100644 index 0000000..47cb6cc --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttEventEmitBenchmarkSuite.h @@ -0,0 +1,87 @@ +#ifndef ECS_BENCHMARKS_ENTTEVENTEMITBENCHMARK_H_ +#define ECS_BENCHMARKS_ENTTEVENTEMITBENCHMARK_H_ + +#include "ExtendedECSBenchmark.h" +#include "entt/EnttApplication.h" +#include "entt/entities/EntityFactory.h" +#include "entt/entities/HeroMonsterEntityFactory.h" +#include + +namespace ecs::benchmarks::entt { + +struct Event { + ::entt::entity entity; +}; + +struct DummyListener { +public: + DummyListener(::entt::registry& registry, + ::entt::dispatcher& dispatcher) : m_registry(registry), m_dispatcher(dispatcher) {} + + void setup() { + m_dispatcher.sink().connect<&DummyListener::receive>(*this); + } + void teardown() { + m_dispatcher.sink().disconnect<&DummyListener::receive>(*this); + } + + void receive(Event& event) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + + auto& comp1 = m_registry.get(event.entity); + auto& comp2 = m_registry.get(event.entity); + + benchmark::DoNotOptimize(comp1); + benchmark::DoNotOptimize(comp2); + //benchmark::DoNotOptimize(event); + } + +private: + ::entt::registry& m_registry; + ::entt::dispatcher& m_dispatcher; +}; + +class EnttEventEmitBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (emit)", EnttApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { +public: + EnttEventEmitBenchmarkSuite() = default; + + explicit EnttEventEmitBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + void BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + + const auto nentities = static_cast(state.range(0)); + EnttApplication::Application app(this->m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + ::entt::dispatcher dispatcher{}; + DummyListener listener (registry, dispatcher); + + listener.setup(); + + auto view = registry.template view(); + for (auto _ : state) { + view.each([&](auto entity, auto& /*comp1*/, auto& /*comp2*/) { + //dummy_each(comp1, comp2); + dispatcher.trigger({.entity = entity}); + }); + } + + listener.teardown(); + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } +}; + +} // namespace ecs::benchmarks::entt + +#endif // ECS_BENCHMARKS_ENTTEVENTEMITBENCHMARK_H_ diff --git a/benchmark/benchmarks/entt-extended/EnttStableEventEmitBenchmarkSuite.cpp b/benchmark/benchmarks/entt-extended/EnttStableEventEmitBenchmarkSuite.cpp new file mode 100644 index 0000000..789f299 --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttStableEventEmitBenchmarkSuite.cpp @@ -0,0 +1,10 @@ +#include "EnttStableEventEmitBenchmarkSuite.h" + +static ecs::benchmarks::entt::EnttStableEventEmitBenchmarkSuite + benchmark_suite({.add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = ENTT_VERSION}); + +static void BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities(state); +} +BENCHMARK(BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); diff --git a/benchmark/benchmarks/entt-extended/EnttStableEventEmitBenchmarkSuite.h b/benchmark/benchmarks/entt-extended/EnttStableEventEmitBenchmarkSuite.h new file mode 100644 index 0000000..5ec9ff4 --- /dev/null +++ b/benchmark/benchmarks/entt-extended/EnttStableEventEmitBenchmarkSuite.h @@ -0,0 +1,85 @@ +#ifndef ECS_BENCHMARKS_ENTTSTABLEEVENTBENCHMARK_H_ +#define ECS_BENCHMARKS_ENTTSTABLEEVENTBENCHMARK_H_ + +#include "ExtendedECSBenchmark.h" +#include "entt/StableEnttApplication.h" +#include "entt/entities/HeroMonsterEntityFactory.h" +#include "entt/entities/StableEntityFactory.h" +#include + +namespace ecs::benchmarks::entt { + +struct Event { + using ComponentOne = ecs::benchmarks::entt::components::StablePositionComponent; + using ComponentTwo = ecs::benchmarks::entt::components::StableVelocityComponent; + + ComponentOne* comp1; + ComponentTwo* comp2; +}; + +struct DummyListener { +public: + DummyListener(::entt::registry& registry, + ::entt::dispatcher& dispatcher) : m_registry(registry), m_dispatcher(dispatcher) {} + + void setup() { + m_dispatcher.sink().connect<&DummyListener::receive>(*this); + } + void teardown() { + m_dispatcher.sink().disconnect<&DummyListener::receive>(*this); + } + + void receive(Event& event) { + benchmark::DoNotOptimize(*event.comp1); + benchmark::DoNotOptimize(*event.comp2); + //benchmark::DoNotOptimize(event); + } + +private: + ::entt::registry& m_registry; + ::entt::dispatcher& m_dispatcher; +}; + +class EnttStableEventEmitBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"entt (emit, stable)", StableEnttApplication, entities::StableEntityFactory, + entities::HeroMonsterEntityFactory> { +public: + EnttStableEventEmitBenchmarkSuite() = default; + + explicit EnttStableEventEmitBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + void BM_TriggerAndUpdateEventsViaDispatcherWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::entt::components::StablePositionComponent; + using ComponentTwo = ecs::benchmarks::entt::components::StableVelocityComponent; + + const auto nentities = static_cast(state.range(0)); + StableEnttApplication::Application app(this->m_options.add_more_complex_system); + EntityManager& registry = app.getEntities(); + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(registry, nentities, entities); + + ::entt::dispatcher dispatcher{}; + DummyListener listener (registry, dispatcher); + + listener.setup(); + + auto view = registry.template view(); + for (auto _ : state) { + view.each([&](auto /*entity*/, auto& comp1, auto& comp2) { + //dummy_each(comp1, comp2); + dispatcher.trigger({.comp1 = &comp1, .comp2 = &comp2}); + }); + } + + listener.teardown(); + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } +}; + +} // namespace ecs::benchmarks::entt + +#endif // ECS_BENCHMARKS_ENTTSTABLEEVENTBENCHMARK_H_ diff --git a/benchmark/benchmarks/flecs-extended/CMakeLists.txt b/benchmark/benchmarks/flecs-extended/CMakeLists.txt index d5eec60..92e52e0 100755 --- a/benchmark/benchmarks/flecs-extended/CMakeLists.txt +++ b/benchmark/benchmarks/flecs-extended/CMakeLists.txt @@ -10,6 +10,37 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-flecs-extended PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-flecs-extended PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-flecs-extended PRIVATE ecs-benchmark-example-flecs) + + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-flecs-extended-event + # NOTE: add new benchmarks here + FlecsEventBenchmarkSuite.cpp FlecsEventBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-flecs-extended-event + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-flecs-extended-event PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-flecs-extended-event PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-flecs-extended-event PRIVATE ecs-benchmark-example-flecs) + + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-flecs-extended-event-emit + # NOTE: add new benchmarks here + FlecsEventEmitBenchmarkSuite.cpp FlecsEventEmitBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-flecs-extended-event-emit + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-flecs-extended-event-emit PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-flecs-extended-event-emit PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-flecs-extended-event-emit PRIVATE ecs-benchmark-example-flecs) \ No newline at end of file diff --git a/benchmark/benchmarks/flecs-extended/FlecsEventBenchmarkSuite.cpp b/benchmark/benchmarks/flecs-extended/FlecsEventBenchmarkSuite.cpp new file mode 100644 index 0000000..14872c6 --- /dev/null +++ b/benchmark/benchmarks/flecs-extended/FlecsEventBenchmarkSuite.cpp @@ -0,0 +1,11 @@ +#include "FlecsEventBenchmarkSuite.h" + +static ecs::benchmarks::flecs::FlecsEventBenchmarkSuite benchmark_suite({ + .add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = std::nullopt, +}); + +static void BM_EnqueueAndUpdateEventsViaObserverWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_EnqueueAndUpdateEventsViaObserverWithMixedEntities(state); +} +BENCHMARK(BM_EnqueueAndUpdateEventsViaObserverWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); \ No newline at end of file diff --git a/benchmark/benchmarks/flecs-extended/FlecsEventBenchmarkSuite.h b/benchmark/benchmarks/flecs-extended/FlecsEventBenchmarkSuite.h new file mode 100644 index 0000000..8b458fd --- /dev/null +++ b/benchmark/benchmarks/flecs-extended/FlecsEventBenchmarkSuite.h @@ -0,0 +1,73 @@ +#ifndef ECS_BENCHMARKS_FLECSEVENTBENCHMARK_H_ +#define ECS_BENCHMARKS_FLECSEVENTBENCHMARK_H_ + +#include "base/components/EmptyComponent.h" +#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" +#include + +namespace ecs::benchmarks::flecs { + +class FlecsEventBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"flecs (enqueue)", FlecsApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { +public: + FlecsEventBenchmarkSuite() = default; + + explicit FlecsEventBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + void BM_EnqueueAndUpdateEventsViaObserverWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + using EventComponent = ecs::benchmarks::base::components::EmptyComponent; + + const auto nentities = static_cast(state.range(0)); + FlecsApplication app(this->m_options.add_more_complex_system); + ::flecs::world& ecs = app.getEntities(); + + // Create observer for custom event + ecs.observer() + .event() + .each([](::flecs::iter& /*it*/, size_t /*i*/, ComponentOne& comp1, ComponentTwo& comp2) { + dummy_each(comp1, comp2); + }); + + // The observer filter can be matched against the entity, so make sure it + // has the Position component before emitting the event. This does not + // trigger the observer yet. + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(ecs, nentities, entities); + + auto q = ecs.query(); + for (auto _ : state) { + // We can only call enqueue events while the world is deferred mode. + ecs.defer_begin(); + q.each([&](::flecs::entity e, ComponentOne& comp1, ComponentTwo& comp2) { + dummy_each(comp1, comp2); + // Emit the custom event + ecs.event() + .id() + .entity(e) + .enqueue(); + }); + // Flushes the queue, and invokes the observer + ecs.defer_end(); + /// @FIXME: flecs_emit: idr = flecs_query_id_record_get(world, id); idr is NULL + } + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } + +}; + +} // namespace ecs::benchmarks::flecs + +#endif // ECS_BENCHMARKS_FLECSBENCHMARK_H_ diff --git a/benchmark/benchmarks/flecs-extended/FlecsEventEmitBenchmarkSuite.cpp b/benchmark/benchmarks/flecs-extended/FlecsEventEmitBenchmarkSuite.cpp new file mode 100644 index 0000000..4adeace --- /dev/null +++ b/benchmark/benchmarks/flecs-extended/FlecsEventEmitBenchmarkSuite.cpp @@ -0,0 +1,12 @@ +#include "FlecsEventEmitBenchmarkSuite.h" + +static ecs::benchmarks::flecs::FlecsEventBenchmarkSuite benchmark_suite({ + .add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = std::nullopt, +}); + +static void BM_EmitAndUpdateEventsViaObserverWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_EmitAndUpdateEventsViaObserverWithMixedEntities(state); +} +BENCHMARK(BM_EmitAndUpdateEventsViaObserverWithMixedEntities)->Apply(ecs::benchmarks::base::BESmallArguments); +/// @NOTE: BEDefaultArguments takes to long \ No newline at end of file diff --git a/benchmark/benchmarks/flecs-extended/FlecsEventEmitBenchmarkSuite.h b/benchmark/benchmarks/flecs-extended/FlecsEventEmitBenchmarkSuite.h new file mode 100644 index 0000000..0b4e8f0 --- /dev/null +++ b/benchmark/benchmarks/flecs-extended/FlecsEventEmitBenchmarkSuite.h @@ -0,0 +1,60 @@ +#ifndef ECS_BENCHMARKS_FLECSEVENTBENCHMARK_H_ +#define ECS_BENCHMARKS_FLECSEVENTBENCHMARK_H_ + +#include "base/components/EmptyComponent.h" +#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" +#include + +namespace ecs::benchmarks::flecs { + +class FlecsEventBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"flecs (emit)", FlecsApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { +public: + FlecsEventBenchmarkSuite() = default; + + explicit FlecsEventBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + void BM_EmitAndUpdateEventsViaObserverWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + using EventComponent = ecs::benchmarks::base::components::EmptyComponent; + + const auto nentities = static_cast(state.range(0)); + FlecsApplication app(this->m_options.add_more_complex_system); + ::flecs::world& ecs = app.getEntities(); + + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(ecs, nentities, entities); + + auto q = ecs.query(); + q.each([&](::flecs::entity e, ComponentOne& /*comp1*/, ComponentTwo& /*comp2*/) { + e.observe([&](::flecs::entity src) { + auto& comp1 = this->m_entities_factory.getComponentOne(ecs, src); + auto& comp2 = this->m_entities_factory.getComponentTwo(ecs, src); + dummy_each(comp1, comp2); + }); + }); + + for (auto _ : state) { + q.each([&](::flecs::entity e, ComponentOne& /*comp1*/, ComponentTwo& /*comp2*/) { + e.emit(); + }); + } + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } +}; + +} // namespace ecs::benchmarks::flecs + +#endif // ECS_BENCHMARKS_FLECSBENCHMARK_H_ diff --git a/benchmark/benchmarks/gaia-ecs-entities/GaiaEcsEntityBenchmarkSuite.cpp b/benchmark/benchmarks/gaia-ecs-entities/GaiaEcsEntityBenchmarkSuite.cpp index 465a638..04ad2c1 100644 --- a/benchmark/benchmarks/gaia-ecs-entities/GaiaEcsEntityBenchmarkSuite.cpp +++ b/benchmark/benchmarks/gaia-ecs-entities/GaiaEcsEntityBenchmarkSuite.cpp @@ -4,6 +4,7 @@ static ecs::benchmarks::gaia_ecs::GaiaEcsEntityBenchmarkSuite benchmark_suite({. ECS_ENTITY_BENCHMARKS(benchmark_suite) +/// @FIXME: crashes /* static void BM_CreateEntitiesInBulk(benchmark::State& state) { benchmark_suite.BM_CreateEntitiesInBulk(state); diff --git a/benchmark/benchmarks/gaia-ecs-extended/GaiaEcsSoABenchmarkSuite.h b/benchmark/benchmarks/gaia-ecs-extended/GaiaEcsSoABenchmarkSuite.h index 343ea61..524e41d 100644 --- a/benchmark/benchmarks/gaia-ecs-extended/GaiaEcsSoABenchmarkSuite.h +++ b/benchmark/benchmarks/gaia-ecs-extended/GaiaEcsSoABenchmarkSuite.h @@ -31,7 +31,7 @@ class GaiaEcsSoABenchmarkSuite final [](auto& world) { return world.query().template all(); }, - [&](::gaia::ecs::Iter iter) { + [&](::gaia::ecs::Iter& iter) { // Position auto vp = iter.view_mut(); auto px = vp.set<0>(); @@ -50,7 +50,7 @@ class GaiaEcsSoABenchmarkSuite final [](auto& world) { return world.query().template all(); }, - [&](::gaia::ecs::Iter iter) { + [&](::gaia::ecs::Iter& iter) { auto vp = iter.view_mut(); auto px = vp.set<0>(); auto py = vp.set<1>(); @@ -74,7 +74,7 @@ class GaiaEcsSoABenchmarkSuite final [](auto& world) { return world.query().template all(); }, - [&](::gaia::ecs::Iter iter) { + [&](::gaia::ecs::Iter& iter) { auto vp = iter.view_mut(); auto px = vp.set<0>(); auto py = vp.set<1>(); diff --git a/benchmark/benchmarks/mustache-extended/CMakeLists.txt b/benchmark/benchmarks/mustache-extended/CMakeLists.txt index 9979f1d..397ac54 100755 --- a/benchmark/benchmarks/mustache-extended/CMakeLists.txt +++ b/benchmark/benchmarks/mustache-extended/CMakeLists.txt @@ -10,6 +10,21 @@ target_include_directories( "$" "$") target_link_libraries(ecs-benchmark-mustache-extended PRIVATE project_warnings project_options) target_link_libraries(ecs-benchmark-mustache-extended PRIVATE ecs-benchmark) - # @NOTE: add libs for example here target_link_libraries(ecs-benchmark-mustache-extended PRIVATE ecs-benchmark-example-mustache) + + +set(INCLUDE_DIR "include") # must be relative paths +# NOTE: rename project in "ecs-benchmark-myecs" +add_executable( + ecs-benchmark-mustache-extended-event + # NOTE: add new benchmarks here + MustacheEventBenchmarkSuite.cpp MustacheEventBenchmarkSuite.h) +target_include_directories( + ecs-benchmark-mustache-extended-event + PRIVATE "$" "$" + "$" "$") +target_link_libraries(ecs-benchmark-mustache-extended-event PRIVATE project_warnings project_options) +target_link_libraries(ecs-benchmark-mustache-extended-event PRIVATE ecs-benchmark) +# @NOTE: add libs for example here +target_link_libraries(ecs-benchmark-mustache-extended-event PRIVATE ecs-benchmark-example-mustache) \ No newline at end of file diff --git a/benchmark/benchmarks/mustache-extended/MustacheEventBenchmarkSuite.cpp b/benchmark/benchmarks/mustache-extended/MustacheEventBenchmarkSuite.cpp new file mode 100644 index 0000000..6fd7108 --- /dev/null +++ b/benchmark/benchmarks/mustache-extended/MustacheEventBenchmarkSuite.cpp @@ -0,0 +1,11 @@ +#include "MustacheEventBenchmarkSuite.h" + +static ecs::benchmarks::mustache::MustacheEventBenchmarkSuite benchmark_suite({ + .add_more_complex_system = ecs::benchmarks::base::add_more_complex_system_t::UseMoreComplexSystems, + .version = std::nullopt, +}); + +static void BM_PostAndUpdateEventsViaReceiverWithMixedEntities(benchmark::State& state) { + benchmark_suite.BM_PostAndUpdateEventsViaReceiverWithMixedEntities(state); +} +BENCHMARK(BM_PostAndUpdateEventsViaReceiverWithMixedEntities)->Apply(ecs::benchmarks::base::BEDefaultArguments); \ No newline at end of file diff --git a/benchmark/benchmarks/mustache-extended/MustacheEventBenchmarkSuite.h b/benchmark/benchmarks/mustache-extended/MustacheEventBenchmarkSuite.h new file mode 100644 index 0000000..33d8917 --- /dev/null +++ b/benchmark/benchmarks/mustache-extended/MustacheEventBenchmarkSuite.h @@ -0,0 +1,96 @@ +#ifndef ECS_BENCHMARKS_MUSTACHEEVENTBENCHMARK_H_ +#define ECS_BENCHMARKS_MUSTACHEEVENTBENCHMARK_H_ + +#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" +#include + +namespace ecs::benchmarks::mustache { + +struct Event { + ::mustache::Entity entity; +}; + +struct DummyEventSystem : public ::mustache::System, public ::mustache::Receiver { + void onConfigure(::mustache::World& world, ::mustache::SystemConfig& config) override { + /// FIXME: Error at mustache/ecs/event_manager.hpp:85:22 + //world.events().subscribe(this); + world.events().subscribe([&](const Event &e) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + benchmark::DoNotOptimize(*world.entities().getComponent(e.entity)); + benchmark::DoNotOptimize(*world.entities().getComponent(e.entity)); + }); + } + void onEvent(const Event &e) { + benchmark::DoNotOptimize(e.entity.id()); + } +}; + +class PostEventSystem : public ::mustache::System { +public: + void onUpdate(::mustache::World& world) override { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + + world.entities().forEach([&](::mustache::Entity entity, const ComponentOne& pos, const ComponentTwo& vel){ + world.events().post(Event{entity}); + }); + } +}; + + +class MustacheEventBenchmarkSuite final + : public ecs::benchmarks::base::ExtendedECSBenchmark<"mustache (event)", MustacheApplication, entities::EntityFactory, + entities::HeroMonsterEntityFactory> { +public: + MustacheEventBenchmarkSuite() = default; + + explicit MustacheEventBenchmarkSuite(ecs::benchmarks::base::ESCBenchmarkOptions options) + : ExtendedECSBenchmark(std::move(options)) {} + + + void BM_PostAndUpdateEventsViaReceiverWithMixedEntities(benchmark::State& state) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + + const auto nentities = static_cast(state.range(0)); + ::mustache::World world; + auto& manager = world.entities(); + std::vector entities; + const base::ComponentsCounter components_counter = + this->template createEntitiesWithMixedComponents(manager, nentities, entities); + + const auto consumeEvent = [&](const Event &e) { + using ComponentOne = ecs::benchmarks::base::components::PositionComponent; + using ComponentTwo = ecs::benchmarks::base::components::VelocityComponent; + benchmark::DoNotOptimize(*world.entities().getComponent(e.entity)); + benchmark::DoNotOptimize(*world.entities().getComponent(e.entity)); + }; + ///@FIXME: add onUpdate ? + world.systems().addSystem(); + //world.systems().addSystem(); + world.events().subscribe(consumeEvent); + world.init(); + + for (auto _ : state) { + world.update(); + } + + this->setCounters(state, entities, components_counter); + //state.counters["events_count"] = static_cast(entities.size()); + } +}; + +} // namespace ecs::benchmarks::mustache + +#endif // ECS_BENCHMARKS_MUSTACHEEVENTBENCHMARK_H_ diff --git a/benchmark/benchmarks/oop/OOPBenchmarkSuite.h b/benchmark/benchmarks/oop/OOPBenchmarkSuite.h index 07b653c..34d56f1 100644 --- a/benchmark/benchmarks/oop/OOPBenchmarkSuite.h +++ b/benchmark/benchmarks/oop/OOPBenchmarkSuite.h @@ -10,7 +10,7 @@ namespace ecs::benchmarks::oop { class OOPBenchmarkSuite final : public ecs::benchmarks::base::BaseECSBenchmark { public: - using EntityManager = typename entities::EntityManager; + using EntityManager = typename entities::OOPEntityManager; using Entity = typename entities::EntityFactory::Entity; const float fakeTimeDelta{1.0F / 60.0F}; diff --git a/cmake/CMakeOptions.cmake b/cmake/CMakeOptions.cmake index 495bae2..044ee19 100644 --- a/cmake/CMakeOptions.cmake +++ b/cmake/CMakeOptions.cmake @@ -78,4 +78,6 @@ if(LIBFUZZER_SUPPORTED else() set(DEFAULT_ENABLE_FUZZING OFF) endif() -option(ENABLE_FUZZING "Enable Fuzzing Builds" ${DEFAULT_ENABLE_FUZZING}) +#option(ENABLE_FUZZING "Enable Fuzzing Builds" ${DEFAULT_ENABLE_FUZZING}) +option(ENABLE_FUZZING "Enable Fuzzing Builds" OFF) +# TODO: add/fix fuzz tests diff --git a/fuzz_test/CMakeLists.txt b/fuzz_test/CMakeLists.txt index 64f7456..08f4e98 100755 --- a/fuzz_test/CMakeLists.txt +++ b/fuzz_test/CMakeLists.txt @@ -1,20 +1,22 @@ # A fuzz test runs until it finds an error. This particular one is going to rely on libFuzzer. # add_executable(ecs-benchmark-fuzz-tester) -target_sources(ecs-benchmark-fuzz-tester PRIVATE ${${CMAKE_PROJECT_NAME}_FUZZ_TEST_SOURCE} ${${CMAKE_PROJECT_NAME}_FUZZ_TEST_HEADERS}) +target_sources(ecs-benchmark-fuzz-tester PRIVATE fuzz_tester.cpp) target_include_directories(ecs-benchmark-fuzz-tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) # @NOTE: add libs here set(THREADS_PREFER_PTHREAD_FLAG ON) -target_link_libraries(${CMAKE_PROJECT_NAME}-fuzz-tester Threads::Threads) +find_package(Threads REQUIRED) +target_link_libraries(ecs-benchmark-fuzz-tester PRIVATE Threads::Threads) -target_link_options(${CMAKE_PROJECT_NAME}-fuzz-tester PRIVATE project_options project_warnings -coverage - -fsanitize=fuzzer,undefined,address) -target_compile_options(${CMAKE_PROJECT_NAME}-fuzz-tester PRIVATE -fsanitize=fuzzer,undefined,address) +target_link_libraries(ecs-benchmark-fuzz-tester PRIVATE project_warnings project_options) +#target_link_options(ecs-benchmark-fuzz-tester PRIVATE -coverage -fsanitize=fuzzer,undefined,address) +#target_compile_options(ecs-benchmark-fuzz-tester PRIVATE -fsanitize=fuzzer,undefined,address) +# @FIXME: c++: error: unrecognized argument to '-fsanitize=' option: 'fuzzer' # Allow short runs during automated testing to see if something new breaks set(FUZZ_RUNTIME 10 CACHE STRING "Number of seconds to run fuzz tests during ctest run") # Default of 10 seconds -add_test(NAME ${CMAKE_PROJECT_NAME}-fuzz-tester-run COMMAND ${CMAKE_PROJECT_NAME}-fuzz-tester -max_total_time=${FUZZ_RUNTIME}) +add_test(NAME ecs-benchmark-fuzz-tester-run COMMAND ecs-benchmark-fuzz-tester -max_total_time=${FUZZ_RUNTIME}) diff --git a/fuzz_test/fuzz_tester.cpp b/fuzz_test/fuzz_tester.cpp index 9fe36d0..2514e05 100755 --- a/fuzz_test/fuzz_tester.cpp +++ b/fuzz_test/fuzz_tester.cpp @@ -2,6 +2,7 @@ #include #include #include +#include [[nodiscard]] auto sum_values(const uint8_t* Data, size_t Size) { constexpr auto scale = 1000; diff --git a/img/AddComponent.svg b/img/AddComponent.svg new file mode 100644 index 0000000..da0e19e --- /dev/null +++ b/img/AddComponent.svg @@ -0,0 +1 @@ +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2MFrameworkEntityXEnTTGinsengFlecspico_ecsgaia-ecsAdd component from EntityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/ComplexSystemsUpdate.svg b/img/ComplexSystemsUpdate.svg index e52275b..58bbd66 100644 --- a/img/ComplexSystemsUpdate.svg +++ b/img/ComplexSystemsUpdate.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µFrameworkEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems)Entities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEnTTEnTT (runtime)EnTT (group)EnTT (emit, stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems)Entities (avg)Time cost per entity \ No newline at end of file diff --git a/img/ComplexSystemsUpdateMixedEntities.svg b/img/ComplexSystemsUpdateMixedEntities.svg index 756440f..edf6a76 100644 --- a/img/ComplexSystemsUpdateMixedEntities.svg +++ b/img/ComplexSystemsUpdateMixedEntities.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µFrameworkEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update systems (7 systems, mixed components)Entities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEnTTEnTT (runtime)EnTT (group)EnTT (emit, stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update systems (7 systems, mixed components)Entities (avg)Time cost per entity \ No newline at end of file diff --git a/img/ComplexSystemsUpdateNoEntities.svg b/img/ComplexSystemsUpdateNoEntities.svg index 9f499d5..36d75bd 100644 --- a/img/ComplexSystemsUpdateNoEntities.svg +++ b/img/ComplexSystemsUpdateNoEntities.svg @@ -1 +1 @@ -−10123456100ms1sFrameworkEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems) with zero entitiesEntities (avg)Time cost per entity \ No newline at end of file +−10123456100ms1sFrameworkEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems) with zero entitiesEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/CreateEmptyEntities.svg b/img/CreateEmptyEntities.svg index f61f496..505106e 100644 --- a/img/CreateEmptyEntities.svg +++ b/img/CreateEmptyEntities.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate (empty) entitiesEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µ100µFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate (empty) entitiesEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/CreateEmptyEntitiesInBulk.svg b/img/CreateEmptyEntitiesInBulk.svg index eabeab0..9fd3ba7 100644 --- a/img/CreateEmptyEntitiesInBulk.svg +++ b/img/CreateEmptyEntitiesInBulk.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µFrameworkEnTTFlecsCreate (empty) entities at onceEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µ100µFrameworkEnTTFlecsCreate (empty) entities at onceEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/CreateEntities.svg b/img/CreateEntities.svg index a20f651..25d92fd 100644 --- a/img/CreateEntities.svg +++ b/img/CreateEntities.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M100ns1µ10µFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate entitiesEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M100ns1µ10µ100µFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate entitiesEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/CreateEntitiesInBulk.svg b/img/CreateEntitiesInBulk.svg index 5f25a72..b537fea 100644 --- a/img/CreateEntitiesInBulk.svg +++ b/img/CreateEntitiesInBulk.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M100ns1µ10µFrameworkEnTTFlecsCreate entities at onceEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M100ns1µ10µ100µFrameworkEnTTFlecsCreate entities at onceEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/CreateNoEntities.svg b/img/CreateNoEntities.svg index 291a5cc..e94e5e5 100644 --- a/img/CreateNoEntities.svg +++ b/img/CreateNoEntities.svg @@ -1 +1 @@ -−10123456100ms1sFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate No entitiesEntities (avg)Time cost per entity \ No newline at end of file +−10123456100ms1sFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate No entitiesEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/DestroyEntities.svg b/img/DestroyEntities.svg index 96bf82b..25bb414 100644 --- a/img/DestroyEntities.svg +++ b/img/DestroyEntities.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µFrameworkEntityXEnTTGinsengFlecspico_ecsgaia-ecsDestroy entitiesEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µ100µFrameworkEntityXEnTTGinsengFlecspico_ecsgaia-ecsDestroy entitiesEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/DestroyEntitiesInBulk.svg b/img/DestroyEntitiesInBulk.svg index a1345c7..b29abcb 100644 --- a/img/DestroyEntitiesInBulk.svg +++ b/img/DestroyEntitiesInBulk.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2MFrameworkEnTTDestroy entities at onceEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M100nsFrameworkEnTTDestroy entities at onceEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/IterateSingleComponent.svg b/img/IterateSingleComponent.svg index 64ffa5c..71a171e 100644 --- a/img/IterateSingleComponent.svg +++ b/img/IterateSingleComponent.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1nsFrameworkgaia-ecs (SoA)Iterate over entities with one componentEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1nsFrameworkgaia-ecsgaia-ecs (SoA)Iterate over entities with one componentEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/IterateThreeComponentsWithMixedEntities.svg b/img/IterateThreeComponentsWithMixedEntities.svg index 56c7449..6515aca 100644 --- a/img/IterateThreeComponentsWithMixedEntities.svg +++ b/img/IterateThreeComponentsWithMixedEntities.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1nsFrameworkEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecs (SoA)Iterate over entities with three componentsEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1nsFrameworkEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecsgaia-ecs (SoA)Iterate over entities with three componentsEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/IterateTwoComponents.svg b/img/IterateTwoComponents.svg index e7a6421..032bd39 100644 --- a/img/IterateTwoComponents.svg +++ b/img/IterateTwoComponents.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1nsFrameworkEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecs (SoA)Iterate over entities with two componentsEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1nsFrameworkEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecsgaia-ecs (SoA)Iterate over entities with two componentsEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/LineAddComponent.svg b/img/LineAddComponent.svg new file mode 100644 index 0000000..97a5c63 --- /dev/null +++ b/img/LineAddComponent.svg @@ -0,0 +1 @@ +0.12512510251002510002510k25100k251M1ns10nsFrameworksEntityXEnTTGinsengFlecspico_ecsgaia-ecsAdd component from EntityEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineComplexSystemsUpdate.svg b/img/LineComplexSystemsUpdate.svg index 0931050..53ab273 100644 --- a/img/LineComplexSystemsUpdate.svg +++ b/img/LineComplexSystemsUpdate.svg @@ -1 +1 @@ -10251002510002510k25100k251M21µ10µ100µ1ms10ms100msFrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems)EntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10ms100msFrameworksEnTTEnTT (runtime)EnTT (group)EnTT (emit, stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems)EntitiesTime for all entities \ No newline at end of file diff --git a/img/LineComplexSystemsUpdateMixedEntities.svg b/img/LineComplexSystemsUpdateMixedEntities.svg index f8560c0..90d3599 100644 --- a/img/LineComplexSystemsUpdateMixedEntities.svg +++ b/img/LineComplexSystemsUpdateMixedEntities.svg @@ -1 +1 @@ -10251002510002510k25100k251M2100ns1µ10µ100µ1ms10ms100msFrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update systems (7 systems, mixed components)EntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10ms100msFrameworksEnTTEnTT (runtime)EnTT (group)EnTT (emit, stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update systems (7 systems, mixed components)EntitiesTime for all entities \ No newline at end of file diff --git a/img/LineComplexSystemsUpdateNoEntities.svg b/img/LineComplexSystemsUpdateNoEntities.svg index 06cf4a2..d1155c2 100644 --- a/img/LineComplexSystemsUpdateNoEntities.svg +++ b/img/LineComplexSystemsUpdateNoEntities.svg @@ -1 +1 @@ -0.12512510251002510002510k25100k251M100ns1µFrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems) with zero entitiesEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M100ns1µFrameworksEnTTEnTT (runtime)EnTT (group)EnTT (stable)GinsengmustacheFlecspico_ecsgaia-ecsgaia-ecs (SoA)Update Systems (7 Systems) with zero entitiesEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineCreateEmptyEntities.svg b/img/LineCreateEmptyEntities.svg index b436e69..08cc9da 100644 --- a/img/LineCreateEmptyEntities.svg +++ b/img/LineCreateEmptyEntities.svg @@ -1 +1 @@ -10251002510002510k25100k251M21µ10µ100µ1ms10ms100ms1s10sFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate (empty) entitiesEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate (empty) entitiesEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineCreateEmptyEntitiesInBulk.svg b/img/LineCreateEmptyEntitiesInBulk.svg index 4eb7ff1..696e56b 100644 --- a/img/LineCreateEmptyEntitiesInBulk.svg +++ b/img/LineCreateEmptyEntitiesInBulk.svg @@ -1 +1 @@ -10251002510002510k25100k251M21µ10µ100µ1ms10msFrameworksEnTTFlecsCreate (empty) entities at onceEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEnTTFlecsCreate (empty) entities at onceEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineCreateEntities.svg b/img/LineCreateEntities.svg index d903fa7..b9d802d 100644 --- a/img/LineCreateEntities.svg +++ b/img/LineCreateEntities.svg @@ -1 +1 @@ -10251002510002510k25100k251M21µ10µ100µ1ms10ms100ms1s10sFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate entitiesEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate entitiesEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineCreateEntitiesInBulk.svg b/img/LineCreateEntitiesInBulk.svg index b2b4784..78a434d 100644 --- a/img/LineCreateEntitiesInBulk.svg +++ b/img/LineCreateEntitiesInBulk.svg @@ -1 +1 @@ -10251002510002510k25100k251M210µ100µ1ms10ms100msFrameworksEnTTFlecsCreate entities at onceEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEnTTFlecsCreate entities at onceEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineCreateNoEntities.svg b/img/LineCreateNoEntities.svg index c67d281..d9b902f 100644 --- a/img/LineCreateNoEntities.svg +++ b/img/LineCreateNoEntities.svg @@ -1 +1 @@ -0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate No entitiesEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsCreate No entitiesEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineDestroyEntities.svg b/img/LineDestroyEntities.svg index 7c7fc3f..ef65128 100644 --- a/img/LineDestroyEntities.svg +++ b/img/LineDestroyEntities.svg @@ -1 +1 @@ -10251002510002510k25100k251M21µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengFlecspico_ecsgaia-ecsDestroy entitiesEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1µ10µ100µFrameworksEntityXEnTTGinsengFlecspico_ecsgaia-ecsDestroy entitiesEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineDestroyEntitiesInBulk.svg b/img/LineDestroyEntitiesInBulk.svg index 653a101..ab2e8c3 100644 --- a/img/LineDestroyEntitiesInBulk.svg +++ b/img/LineDestroyEntitiesInBulk.svg @@ -1 +1 @@ -10251002510002510k25100k251M21µ10µ100µ1ms10ms100msFrameworksEnTTDestroy entities at onceEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M100ns1µFrameworksEnTTDestroy entities at onceEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineIterateSingleComponent.svg b/img/LineIterateSingleComponent.svg index 5f686e3..c731a5d 100644 --- a/img/LineIterateSingleComponent.svg +++ b/img/LineIterateSingleComponent.svg @@ -1 +1 @@ -10251002510002510k25100k251M2100ns1µ10µ100µ1msFrameworksgaia-ecs (SoA)Iterate over entities with one componentEntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M210ns100ns1µ10µ100µ1msFrameworksgaia-ecsgaia-ecs (SoA)Iterate over entities with one componentEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineIterateThreeComponentsWithMixedEntities.svg b/img/LineIterateThreeComponentsWithMixedEntities.svg index 2ab2bb0..515122d 100644 --- a/img/LineIterateThreeComponentsWithMixedEntities.svg +++ b/img/LineIterateThreeComponentsWithMixedEntities.svg @@ -1 +1 @@ -10251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10msFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecs (SoA)Iterate over entities with three componentsEntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M21ns10ns100ns1µ10µ100µ1ms10msFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecsgaia-ecs (SoA)Iterate over entities with three componentsEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineIterateTwoComponents.svg b/img/LineIterateTwoComponents.svg index 9e015eb..5c7a659 100644 --- a/img/LineIterateTwoComponents.svg +++ b/img/LineIterateTwoComponents.svg @@ -1 +1 @@ -10251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10msFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecs (SoA)Iterate over entities with two componentsEntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M21ns10ns100ns1µ10µ100µ1ms10msFrameworksEnTT (full-owning group)EnTT (non-owning group)EnTT (partial-owning group)gaia-ecsgaia-ecs (SoA)Iterate over entities with two componentsEntitiesTime for all entities \ No newline at end of file diff --git a/img/LinePublishAndUpdateEvents.svg b/img/LinePublishAndUpdateEvents.svg new file mode 100644 index 0000000..3dd7a92 --- /dev/null +++ b/img/LinePublishAndUpdateEvents.svg @@ -0,0 +1 @@ +12510251002510002510k25100k251M21ns10ns100ns1µ10µ100µ1ms10ms100msFrameworksEnTT (events)EnTT (component)EnTT (emit)EnTT (emit, stable)Publish and Update events with three componentsEntitiesTime for all events \ No newline at end of file diff --git a/img/LineRemoveAddComponent.svg b/img/LineRemoveAddComponent.svg index d363b09..df3efbf 100644 --- a/img/LineRemoveAddComponent.svg +++ b/img/LineRemoveAddComponent.svg @@ -1 +1 @@ -10251002510002510k25100k251M2100ns1µ10µ100µ1ms10ms100ms1s10sFrameworksEntityXEnTTGinsengFlecspico_ecsgaia-ecsRemove and add component from EntityEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1ns10nsFrameworksEntityXEnTTGinsengFlecspico_ecsgaia-ecsRemove and add component from EntityEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineSystemsUpdate.svg b/img/LineSystemsUpdate.svg index 5f755bb..1e0eaa7 100644 --- a/img/LineSystemsUpdate.svg +++ b/img/LineSystemsUpdate.svg @@ -1 +1 @@ -10251002510002510k25100k251M2100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems)EntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems)EntitiesTime for all entities \ No newline at end of file diff --git a/img/LineSystemsUpdateMixedEntities.svg b/img/LineSystemsUpdateMixedEntities.svg index 98cce4e..b96654b 100644 --- a/img/LineSystemsUpdateMixedEntities.svg +++ b/img/LineSystemsUpdateMixedEntities.svg @@ -1 +1 @@ -10251002510002510k25100k251M2100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems, mixed components)EntitiesTime for all entities \ No newline at end of file +12510251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems, mixed components)EntitiesTime for all entities \ No newline at end of file diff --git a/img/LineSystemsUpdateNoEntities.svg b/img/LineSystemsUpdateNoEntities.svg index 0b44cf5..844720e 100644 --- a/img/LineSystemsUpdateNoEntities.svg +++ b/img/LineSystemsUpdateNoEntities.svg @@ -1 +1 @@ -0.12512510251002510002510k25100k251M10ns100nsFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems) with zero entitiesEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M10ns100nsFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems) with zero entitiesEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineUnpackNoComponent.svg b/img/LineUnpackNoComponent.svg index f9490bf..a99e6e0 100644 --- a/img/LineUnpackNoComponent.svg +++ b/img/LineUnpackNoComponent.svg @@ -1 +1 @@ -10251002510002510k25100k251M21ns10ns100ns1µ10µ100µ1ms10msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet No component from EntityEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1ns10nsFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet No component from EntityEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineUnpackOneComponent.svg b/img/LineUnpackOneComponent.svg index 0bf2f0d..42a589a 100644 --- a/img/LineUnpackOneComponent.svg +++ b/img/LineUnpackOneComponent.svg @@ -1 +1 @@ -10251002510002510k25100k251M210ns100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet one component from EntityEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1ns10nsFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet one component from EntityEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineUnpackOneComponentNoEntities.svg b/img/LineUnpackOneComponentNoEntities.svg index 1177580..276f4ab 100644 --- a/img/LineUnpackOneComponentNoEntities.svg +++ b/img/LineUnpackOneComponentNoEntities.svg @@ -1 +1 @@ -0.12512510251002510002510k25100k251M100ms1s10sFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet component from No EntityEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M100ms1s10sFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet component from No EntityEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineUnpackThreeComponents.svg b/img/LineUnpackThreeComponents.svg index 2c26541..88d35bc 100644 --- a/img/LineUnpackThreeComponents.svg +++ b/img/LineUnpackThreeComponents.svg @@ -1 +1 @@ -510251002510002510k25100k251M10ns100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet three components from EntityEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1ns10nsFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet three components from EntityEntitiesTime for all entities \ No newline at end of file diff --git a/img/LineUnpackTwoComponents.svg b/img/LineUnpackTwoComponents.svg index f806160..6ba3c45 100644 --- a/img/LineUnpackTwoComponents.svg +++ b/img/LineUnpackTwoComponents.svg @@ -1 +1 @@ -10251002510002510k25100k251M2100ns1µ10µ100µ1ms10ms100msFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet two components from entityEntitiesTime for all entities \ No newline at end of file +0.12512510251002510002510k25100k251M1ns10nsFrameworksEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet two components from entityEntitiesTime for all entities \ No newline at end of file diff --git a/img/PublishAndUpdateEvents.svg b/img/PublishAndUpdateEvents.svg new file mode 100644 index 0000000..d019fab --- /dev/null +++ b/img/PublishAndUpdateEvents.svg @@ -0,0 +1 @@ +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10nsFrameworkEnTT (events)EnTT (component)EnTT (emit)EnTT (emit, stable)Publish and Update events with three componentsEntities (avg)Time cost per event \ No newline at end of file diff --git a/img/RemoveAddComponent.svg b/img/RemoveAddComponent.svg index bbd6716..1e225b8 100644 --- a/img/RemoveAddComponent.svg +++ b/img/RemoveAddComponent.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100ns1µ10µFrameworkEntityXEnTTGinsengFlecspico_ecsgaia-ecsRemove and add component from EntityEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEntityXEnTTGinsengFlecspico_ecsgaia-ecsRemove and add component from EntityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/SystemsUpdate.svg b/img/SystemsUpdate.svg index e786ca6..42e5315 100644 --- a/img/SystemsUpdate.svg +++ b/img/SystemsUpdate.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems)Entities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems)Entities (avg)Time cost per entity \ No newline at end of file diff --git a/img/SystemsUpdateMixedEntities.svg b/img/SystemsUpdateMixedEntities.svg index 03ff250..516c4ef 100644 --- a/img/SystemsUpdateMixedEntities.svg +++ b/img/SystemsUpdateMixedEntities.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems, mixed components)Entities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10ns100nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems, mixed components)Entities (avg)Time cost per entity \ No newline at end of file diff --git a/img/SystemsUpdateNoEntities.svg b/img/SystemsUpdateNoEntities.svg index 598010a..5c0e4cf 100644 --- a/img/SystemsUpdateNoEntities.svg +++ b/img/SystemsUpdateNoEntities.svg @@ -1 +1 @@ -−10123456100ms1sFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems) with zero entitiesEntities (avg)Time cost per entity \ No newline at end of file +−10123456100ms1sFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsUpdate systems (2 systems) with zero entitiesEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/UnpackNoComponent.svg b/img/UnpackNoComponent.svg index d004ca0..ede7cdc 100644 --- a/img/UnpackNoComponent.svg +++ b/img/UnpackNoComponent.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1ns10nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet No component from EntityEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M1ns10nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet No component from EntityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/UnpackOneComponent.svg b/img/UnpackOneComponent.svg index 336db51..c89798d 100644 --- a/img/UnpackOneComponent.svg +++ b/img/UnpackOneComponent.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet one component from EntityEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet one component from EntityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/UnpackOneComponentNoEntities.svg b/img/UnpackOneComponentNoEntities.svg index 86a8ce1..ecf9f3b 100644 --- a/img/UnpackOneComponentNoEntities.svg +++ b/img/UnpackOneComponentNoEntities.svg @@ -1 +1 @@ -−10123456100ms1sFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet component from No EntityEntities (avg)Time cost per entity \ No newline at end of file +−10123456100ms1sFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet component from No EntityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/UnpackThreeComponents.svg b/img/UnpackThreeComponents.svg index 452272a..6600c54 100644 --- a/img/UnpackThreeComponents.svg +++ b/img/UnpackThreeComponents.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M10ns100nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet three components from EntityEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M10ns100nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet three components from EntityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/img/UnpackTwoComponents.svg b/img/UnpackTwoComponents.svg index 48f5ba3..9c5dfb1 100644 --- a/img/UnpackTwoComponents.svg +++ b/img/UnpackTwoComponents.svg @@ -1 +1 @@ -[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet two components from entityEntities (avg)Time cost per entity \ No newline at end of file +[8, 128][256, 1024][2048, 8192][16k, 65k][131k, 524k]1M2M10nsFrameworkEntityXEnTTGinsengmustacheFlecspico_ecsgaia-ecsGet two components from entityEntities (avg)Time cost per entity \ No newline at end of file diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index ee884a0..630eb9d 100755 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,4 +1,3 @@ -# more 3rd party dependencies +# more external dependencies -add_subdirectory(openecs) -add_subdirectory(pico_ecs) \ No newline at end of file +add_subdirectory(openecs) \ No newline at end of file diff --git a/libs/openecs/CMakeLists.txt b/libs/openecs/CMakeLists.txt index be10963..e0560b8 100644 --- a/libs/openecs/CMakeLists.txt +++ b/libs/openecs/CMakeLists.txt @@ -7,4 +7,4 @@ project(OpenEcs LANGUAGES C CXX) add_library(OpenEcs INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/ecs.h) -target_include_directories(OpenEcs INTERFACE "$") \ No newline at end of file +target_include_directories(OpenEcs INTERFACE "$") diff --git a/libs/pico_ecs/CMakeLists.txt b/libs/pico_ecs/CMakeLists.txt deleted file mode 100644 index c74a02e..0000000 --- a/libs/pico_ecs/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -cmake_minimum_required(VERSION 3.24) - -# https://github.com/empyreanx/pico_headers -CPMAddPackage( - NAME pico_headers - VERSION 2.3 - GITHUB_REPOSITORY empyreanx/pico_headers - # TODO: set current version, use master (no release version) - GIT_TAG main - DOWNLOAD_ONLY True -) -if(pico_headers_ADDED) - add_library(pico_headers INTERFACE) - target_include_directories(pico_headers SYSTEM INTERFACE ${pico_headers_SOURCE_DIR}) - - project(pico_ecs LANGUAGES C) - add_library(pico_ecs INTERFACE ${pico_headers_SOURCE_DIR}/pico_ecs.h) - add_library(pico_headers::pico_ecs ALIAS pico_ecs) - target_include_directories(pico_ecs INTERFACE "$") - - target_compile_definitions(pico_ecs INTERFACE $<$:NDEBUG>) -endif() - diff --git a/libs/pico_ecs/LICENSE b/libs/pico_ecs/LICENSE deleted file mode 100644 index 5de3337..0000000 --- a/libs/pico_ecs/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2021 James McLean - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the -use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software in a - product, an acknowledgment in the product documentation would be appreciated - but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. diff --git a/libs/pico_ecs/include/pico_ecs.h b/libs/pico_ecs/include/pico_ecs.h deleted file mode 100644 index 1e31756..0000000 --- a/libs/pico_ecs/include/pico_ecs.h +++ /dev/null @@ -1,1546 +0,0 @@ -/** -@file pico_ecs.h -@brief A pure and simple ECS written in C99. - ----------------------------------------------------------------------------- -Licensing information at end of header ----------------------------------------------------------------------------- - -Features: ---------- -- Written in C99 -- Single header library for easy build system integration -- Excellent performance -- Pure ECS design (strict separation between data and logic) -- Simple and concise API -- Permissive license (zlib or public domain) - -Summary: --------- - -This library implements an ECS (Entity-Component-System). Entities -(sometimes called game objects) are defined by their components. For -example, an entity might have position, sprite, and physics components. -Systems operate on the components of entities that match the system's -requirements. Entities are matched to systems based upon which components -they have and also the system's matching crieria. - -In the above example, a sprite renderer system would match entities having -poition and sprite components. The system would send the appropriate -geometry and texture ID to the game's graphics API. - -Traditional game engines tightly couple state with logic. For example, in -C++ a game object typically has its own update method that operates -on that state. They also usually rely heavily on inheritance. - -If the state specified by the class changes this could ripple through the -class, and perhaps subclasses as well. It could well be that the class no -longer belongs in the existing class hierarchy forcing even more revisions. -It could even be true that a class doesn't neatly fit into the inheritance -tree at all. - -An ECS solves these problems while also granting more flexibility in -general. In an ECS there is a clear separation between data (components) and -logic (systems), which makes it possible to build complex simulations with -fewer assumptions about how that data will be used. In an ECS it effortless -to change functionality, by either adding or removing components from -entities, and/or by changing system requirements. Adding new logic is also -simple as well, just register a new system! - -Please see the examples and unit tests for more details. - -Usage: ------- - -To use this library in your project, add the following - -> #define PICO_ECS_IMPLEMENTATION -> #include "pico_ecs.h" - -to a source file (once), then simply include the header normally. - -Constants: --------- - -- PICO_ECS_MAX_COMPONENTS (default: 32) -- PICO_ECS_MAX_SYSTEMS (default: 16) - -Must be defined before PICO_ECS_IMPLEMENTATION - -Todo: ------ -- Better default assertion macro -- Port Rogue demo to Windows -*/ - -#ifndef PICO_ECS_H -#define PICO_ECS_H - -#include // bool, true, false -#include // size_t -#include // uint32_t - -#ifdef __cplusplus -extern "C" { -#endif - - /** -* @brief ECS context - */ - typedef struct ecs_s ecs_t; - - /** -* @brief ID used for entity and components - */ - typedef uint32_t ecs_id_t; - -/** -* @brief NULL/invalid/undefined value - */ -#define ECS_NULL ((ecs_id_t)-1) - - /** -* @brief Return code for update callback and calling functions - */ - typedef int8_t ecs_ret_t; - -/** -* @brief Determine delta-time type - */ -#ifndef ECS_DT_TYPE -#define ECS_DT_TYPE double -#endif - - typedef ECS_DT_TYPE ecs_dt_t; - - /** -* @brief Creates an ECS instance. -* -* @param entity_count The inital number of pooled entities -* @param mem_ctx The Context for a custom allocator -* -* @returns An ECS instance or NULL if out of memory - */ - ecs_t* ecs_new(size_t entity_count, void* mem_ctx); - - /** -* @brief Destroys an ECS instance -* -* @param ecs The ECS instance - */ - void ecs_free(ecs_t* ecs); - - /** -* @brief Removes all entities from the ECS, preserving systems and components. - */ - void ecs_reset(ecs_t* ecs); - - /** -* @brief Called when a component is created (via ecs_add) -* -* @param ecs The ECS instance -* @param entity_id The entity being constructed -* @param ptr The pointer to the component -* @param udata The user data passed to the callback - */ - typedef void (*ecs_constructor_fn)(ecs_t* ecs, - ecs_id_t entity_id, - void* ptr, - void* args); - - /** -* @brief Called when a component is destroyed (via ecs_remove or ecs_destroy) -* -* @param ecs The ECS instance -* @param entity_id The entity being destoryed -* @param ptr The pointer to the component -* @param udata The user data passed to the callback - */ - typedef void (*ecs_destructor_fn)(ecs_t* ecs, - ecs_id_t entity_id, - void* ptr); - - /** -* @brief Registers a component -* -* Registers a component with the specfied size in bytes. Components define the -* game state (usually contained within structs) and are manipulated by systems. -* -* @param ecs The ECS instance -* @param size The number of bytes to allocate for each component instance -* @param constructor Called when a component is created (disabled if NULL) -* @param destructor Called when a component is destroyed (disabled if NULL) -* @param udata Data passed to callbacks (can be NULL) -* @returns The component's ID - */ - ecs_id_t ecs_register_component(ecs_t* ecs, - size_t size, - ecs_constructor_fn constructor, - ecs_destructor_fn destructor); - - /** -* @brief System update callback -* -* Systems implement the core logic of an ECS by manipulating entities -* and components. -* -* @param ecs The ECS instance -* @param entities An array of entity IDs managed by the system -* @param entity_count The number of entities in the array -* @param dt The time delta -* @param udata The user data associated with the system - */ - typedef ecs_ret_t (*ecs_system_fn)(ecs_t* ecs, - ecs_id_t* entities, - int entity_count, - ecs_dt_t dt, - void* udata); - - /** -* @brief Called when an entity is added to a system -* -* @param ecs The ECS instance -* @param entity_id The enitty being added -* @param udata The user data passed to the callback - */ - typedef void (*ecs_added_fn)(ecs_t* ecs, ecs_id_t entity_id, void* udata); - - /** -* @brief Called when an entity is removed from a system -* -* @param ecs The ECS instance -* @param entity_id The enitty being removed -* @param udata The user data passed to the callback - */ - typedef void (*ecs_removed_fn)(ecs_t* ecs, ecs_id_t entity_id, void* udata); - - /** -* @brief Registers a system -* -* Registers a system with the specified parameters. Systems contain the -* core logic of a game by manipulating game state as defined by components. -* -* @param ecs The ECS instance -* @param system_cb Callback that is fired every update -* @param add_cb Called when an entity is added to the system (can be NULL) -* @param remove_cb Called when an entity is removed from the system (can be NULL) -* @param udata The user data passed to the callbacks -* @returns The system's ID - */ - ecs_id_t ecs_register_system(ecs_t* ecs, - ecs_system_fn system_cb, - ecs_added_fn add_cb, - ecs_removed_fn remove_cb, - void* udata); - /** -* @brief Determines which components are available to the specified system. -* -* @param ecs The ECS instance -* @param sys_id The target system ID -* @param comp_id The component ID - */ - void ecs_require_component(ecs_t* ecs, ecs_id_t sys_id, ecs_id_t comp_id); - - /** -* @brief Excludes entities having the specified component from being added to -* the target system. -* -* @param ecs The ECS instance -* @param sys_id The target system ID -* @param comp_id The component ID tp exclude - */ - void ecs_exclude_component(ecs_t* ecs, ecs_id_t sys_id, ecs_id_t comp_id); - - /** -* @brief Enables a system -* -* @param ecs The ECS instance -* @param sys_id The specified system ID - */ - void ecs_enable_system(ecs_t* ecs, ecs_id_t sys_id); - - /** -* @brief Disables a system -* -* @param ecs The ECS instance -* @param sys_id The specified system ID - */ - void ecs_disable_system(ecs_t* ecs, ecs_id_t sys_id); - - /** -* @brief Creates an entity -* -* @param ecs The ECS instance -* -* @returns The new entity ID - */ - ecs_id_t ecs_create(ecs_t* ecs); - - /** -* @brief Returns true if the entity is currently active -* -* @param ecs The ECS instance -* @param entity_id The target entity - */ - bool ecs_is_ready(ecs_t* ecs, ecs_id_t entity_id); - - /** -* @brief Destroys an entity -* -* Destroys an entity, releasing resources and returning it to the pool. -* -* @param ecs The ECS instance -* @param entity_id The ID of the entity to destroy - */ - void ecs_destroy(ecs_t* ecs, ecs_id_t entity_id); - - /** -* @brief Test if entity has the specified component -* -* @param ecs The ECS instance -* @param entity_id The entity ID -* @param comp_id The component ID -* -* @returns True if the entity has the component - */ - bool ecs_has(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id); - - /** -* @brief Adds a component instance to an entity -* -* @param ecs The ECS instance -* @param entity_id The entity ID -* @param comp_id The component ID -* -* @returns The component instance - */ - void* ecs_add(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id, void* args); - - /** -* @brief Gets a component instance associated with an entity -* -* @param ecs The ECS instance -* @param entity_id The entity ID -* @param comp_id The component ID -* -* @returns The component instance - */ - void* ecs_get(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id); - - /** -* @brief Removes a component instance from an entity -* -* @param ecs The ECS instance -* @param entity_id The entity ID -* @param comp_id The component ID - */ - void ecs_remove(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id); - - /** -* @brief Queues an entity for destruction at the end of system execution -* -* Queued entities are destroyed after the curent iteration. -* -* @param ecs The ECS instance -* @param entity_id The ID of the entity to destroy - */ - void ecs_queue_destroy(ecs_t* ecs, ecs_id_t entity_id); - - /** -* @brief Queues a component for removable -* -* Queued entity/component pairs that will be deleted after the current system -* returns -* -* @param ecs The ECS instance -* @param entity_id The ID of the entity that has the component -* @param comp_id The component to remove - */ - void ecs_queue_remove(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id); - - /** -* @brief Update an individual system -* -* This function should be called once per frame. -* -* @param ecs The ECS instance -* @param sys_id The system to update -* @param dt The time delta - */ - ecs_ret_t ecs_update_system(ecs_t* ecs, ecs_id_t sys_id, ecs_dt_t dt); - - /** -* @brief Updates all systems -* -* This function should be called once per frame. -* -* @param ecs The ECS instance -* @param dt The time delta - */ - ecs_ret_t ecs_update_systems(ecs_t* ecs, ecs_dt_t dt); - -#ifdef __cplusplus -} -#endif - -#endif // PICO_ECS_H - -#ifdef PICO_ECS_IMPLEMENTATION // Define once - -#include // uint32_t -#include // malloc, realloc, free -#include // memcpy, memset - -#ifndef PICO_ECS_MAX_COMPONENTS -#define PICO_ECS_MAX_COMPONENTS 32 -#endif - -#ifndef PICO_ECS_MAX_SYSTEMS -#define PICO_ECS_MAX_SYSTEMS 16 -#endif - -#ifdef NDEBUG -#define PICO_ECS_ASSERT(expr) ((void)0) -#else -#ifndef PICO_ECS_ASSERT -#include -#define PICO_ECS_ASSERT(expr) (assert(expr)) -#endif -#endif - -#if !defined(PICO_ECS_MALLOC) || !defined(PICO_ECS_REALLOC) || !defined(PICO_ECS_FREE) -#include -#define PICO_ECS_MALLOC(size, ctx) (malloc(size)) -#define PICO_ECS_REALLOC(ptr, size, ctx) (realloc(ptr, size)) -#define PICO_ECS_FREE(ptr, ctx) (free(ptr)) -#endif - -/*============================================================================= -* Internal aliases -*============================================================================*/ - -#define ECS_ASSERT PICO_ECS_ASSERT -#define ECS_MAX_COMPONENTS PICO_ECS_MAX_COMPONENTS -#define ECS_MAX_SYSTEMS PICO_ECS_MAX_SYSTEMS -#define ECS_MALLOC PICO_ECS_MALLOC -#define ECS_REALLOC PICO_ECS_REALLOC -#define ECS_FREE PICO_ECS_FREE - -/*============================================================================= -* Internal data structures -*============================================================================*/ - -#if ECS_MAX_COMPONENTS <= 32 -typedef uint32_t ecs_bitset_t; -#elif ECS_MAX_COMPONENTS <= 64 -typedef uint64_t ecs_bitset_t; -#else -#define ECS_BITSET_WIDTH 64 -#define ECS_BITSET_SIZE (((ECS_MAX_COMPONENTS - 1) / ECS_BITSET_WIDTH) + 1) - -typedef struct -{ - uint64_t array[ECS_BITSET_SIZE]; -} ecs_bitset_t; -#endif // ECS_MAX_COMPONENTS - -// Data-structure for a packed array implementation that provides O(1) functions -// for adding, removing, and accessing entity IDs -typedef struct -{ - size_t capacity; - size_t size; - size_t* sparse; - ecs_id_t* dense; -} ecs_sparse_set_t; - -// Data-structure for an ID pool that provides O(1) operations for pooling IDs -typedef struct -{ - size_t capacity; - size_t size; - ecs_id_t* array; -} ecs_stack_t; - -typedef struct -{ - size_t capacity; - size_t count; - size_t size; - void* data; -} ecs_array_t; - -typedef struct -{ - ecs_bitset_t comp_bits; - bool ready; -} ecs_entity_t; - -typedef struct -{ - ecs_constructor_fn constructor; - ecs_destructor_fn destructor; -} ecs_comp_t; - -typedef struct -{ - bool active; - ecs_sparse_set_t entity_ids; - ecs_system_fn system_cb; - ecs_added_fn add_cb; - ecs_removed_fn remove_cb; - ecs_bitset_t require_bits; - ecs_bitset_t exclude_bits; - void* udata; -} ecs_sys_t; - -struct ecs_s -{ - ecs_stack_t entity_pool; - ecs_stack_t destroy_queue; - ecs_stack_t remove_queue; - ecs_entity_t* entities; - size_t entity_count; - ecs_comp_t comps[ECS_MAX_COMPONENTS]; - ecs_array_t comp_arrays[ECS_MAX_COMPONENTS]; - size_t comp_count; - ecs_sys_t systems[ECS_MAX_SYSTEMS]; - size_t system_count; - void* mem_ctx; -}; - -/*============================================================================= -* Internal realloc wrapper -*============================================================================*/ -void* ecs_realloc_zero(ecs_t* ecs, void* ptr, size_t old_size, size_t new_size); - -/*============================================================================= -* Internal functions to flush destroyed entities and removed component -*============================================================================*/ -static void ecs_flush_destroyed(ecs_t* ecs); -static void ecs_flush_removed(ecs_t* ecs); - -/*============================================================================= -* Internal bit set functions -*============================================================================*/ -static inline void ecs_bitset_flip(ecs_bitset_t* set, int bit, bool on); -static inline bool ecs_bitset_is_zero(ecs_bitset_t* set); -static inline bool ecs_bitset_test(ecs_bitset_t* set, int bit); -static inline ecs_bitset_t ecs_bitset_and(ecs_bitset_t* set1, ecs_bitset_t* set2); -static inline ecs_bitset_t ecs_bitset_or(ecs_bitset_t* set1, ecs_bitset_t* set2); -static inline ecs_bitset_t ecs_bitset_not(ecs_bitset_t* set); -static inline bool ecs_bitset_equal(ecs_bitset_t* set1, ecs_bitset_t* set2); -static inline bool ecs_bitset_true(ecs_bitset_t* set); - -/*============================================================================= -* Internal sparse set functions -*============================================================================*/ -static void ecs_sparse_set_init(ecs_t* ecs, ecs_sparse_set_t* set, size_t capacity); -static void ecs_sparse_set_free(ecs_t* ecs, ecs_sparse_set_t* set); -static bool ecs_sparse_set_add(ecs_t* ecs, ecs_sparse_set_t* set, ecs_id_t id); -static size_t ecs_sparse_set_find(ecs_sparse_set_t* set, ecs_id_t id); -static bool ecs_sparse_set_remove(ecs_sparse_set_t* set, ecs_id_t id); - -/*============================================================================= -* Internal system entity add/remove functions -*============================================================================*/ -static bool ecs_entity_system_test(ecs_bitset_t* require_bits, - ecs_bitset_t* exclude_bits, - ecs_bitset_t* entity_bits); - -/*============================================================================= -* Internal ID pool functions -*============================================================================*/ -static void ecs_stack_init(ecs_t* ecs, ecs_stack_t* pool, int capacity); -static void ecs_stack_free(ecs_t* ecs, ecs_stack_t* pool); -static void ecs_stack_push(ecs_t* ecs, ecs_stack_t* pool, ecs_id_t id); -static ecs_id_t ecs_stack_pop(ecs_stack_t* pool); -static int ecs_stack_size(ecs_stack_t* pool); - -/*============================================================================= -* Internal array functions -*============================================================================*/ -static void ecs_array_init(ecs_t* ecs, ecs_array_t* array, size_t size, size_t capacity); -static void ecs_array_free(ecs_t* ecs, ecs_array_t* array); -static void ecs_array_resize(ecs_t* ecs, ecs_array_t* array, size_t capacity); - -/*============================================================================= -* Internal validation functions -*============================================================================*/ -#ifndef NDEBUG -static bool ecs_is_not_null(void* ptr); -static bool ecs_is_valid_component_id(ecs_id_t id); -static bool ecs_is_valid_system_id(ecs_id_t id); -static bool ecs_is_entity_ready(ecs_t* ecs, ecs_id_t entity_id); -static bool ecs_is_component_ready(ecs_t* ecs, ecs_id_t comp_id); -static bool ecs_is_system_ready(ecs_t* ecs, ecs_id_t sys_id); -#endif // NDEBUG -/*============================================================================= -* Public API implementation -*============================================================================*/ - -ecs_t* ecs_new(size_t entity_count, void* mem_ctx) -{ - ECS_ASSERT(entity_count > 0); - - ecs_t* ecs = (ecs_t*)ECS_MALLOC(sizeof(ecs_t), mem_ctx); - - // Out of memory - if (NULL == ecs) - return NULL; - - memset(ecs, 0, sizeof(ecs_t)); - - ecs->entity_count = entity_count; - ecs->mem_ctx = mem_ctx; - - // Initialize entity pool and queues - ecs_stack_init(ecs, &ecs->entity_pool, entity_count); - ecs_stack_init(ecs, &ecs->destroy_queue, entity_count); - ecs_stack_init(ecs, &ecs->remove_queue, entity_count * 2); - - // Allocate entity array - ecs->entities = (ecs_entity_t*)ECS_MALLOC(ecs->entity_count * sizeof(ecs_entity_t), - ecs->mem_ctx); - - // Zero entity array - memset(ecs->entities, 0, ecs->entity_count * sizeof(ecs_entity_t)); - - // Pre-populate the the ID pool - for (ecs_id_t id = 0; id < entity_count; id++) - { - ecs_stack_push(ecs, &ecs->entity_pool, id); - } - - return ecs; -} - -void ecs_free(ecs_t* ecs) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - - for (ecs_id_t entity_id = 0; entity_id < ecs->entity_count; entity_id++) - { - if (ecs->entities[entity_id].ready) - ecs_destroy(ecs, entity_id); - } - - ecs_stack_free(ecs, &ecs->entity_pool); - ecs_stack_free(ecs, &ecs->destroy_queue); - ecs_stack_free(ecs, &ecs->remove_queue); - - for (ecs_id_t comp_id = 0; comp_id < ecs->comp_count; comp_id++) - { - ecs_array_t* comp_array = &ecs->comp_arrays[comp_id]; - ecs_array_free(ecs, comp_array); - } - - for (ecs_id_t sys_id = 0; sys_id < ecs->system_count; sys_id++) - { - ecs_sys_t* sys = &ecs->systems[sys_id]; - ecs_sparse_set_free(ecs, &sys->entity_ids); - } - - ECS_FREE(ecs->entities, ecs->mem_ctx); - ECS_FREE(ecs, ecs->mem_ctx); -} - -void ecs_reset(ecs_t* ecs) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - - for (ecs_id_t entity_id = 0; entity_id < ecs->entity_count; entity_id++) - { - if (ecs->entities[entity_id].ready) - ecs_destroy(ecs, entity_id); - } - - ecs->entity_pool.size = 0; - ecs->destroy_queue.size = 0; - ecs->remove_queue.size = 0; - - memset(ecs->entities, 0, ecs->entity_count * sizeof(ecs_entity_t)); - - for (ecs_id_t entity_id = 0; entity_id < ecs->entity_count; entity_id++) - { - ecs_stack_push(ecs, &ecs->entity_pool, entity_id); - } - - for (ecs_id_t sys_id = 0; sys_id < ecs->system_count; sys_id++) - { - ecs->systems[sys_id].entity_ids.size = 0; - } -} - -ecs_id_t ecs_register_component(ecs_t* ecs, - size_t size, - ecs_constructor_fn constructor, - ecs_destructor_fn destructor) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs->comp_count < ECS_MAX_COMPONENTS); - ECS_ASSERT(size > 0); - - ecs_id_t comp_id = ecs->comp_count; - - ecs_array_t* comp_array = &ecs->comp_arrays[comp_id]; - ecs_array_init(ecs, comp_array, size, ecs->entity_count); - - ecs->comps[comp_id].constructor = constructor; - ecs->comps[comp_id].destructor = destructor; - - ecs->comp_count++; - - return comp_id; -} - -ecs_id_t ecs_register_system(ecs_t* ecs, - ecs_system_fn system_cb, - ecs_added_fn add_cb, - ecs_removed_fn remove_cb, - void* udata) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs->system_count < ECS_MAX_SYSTEMS); - ECS_ASSERT(NULL != system_cb); - - ecs_id_t sys_id = ecs->system_count; - ecs_sys_t* sys = &ecs->systems[sys_id]; - - ecs_sparse_set_init(ecs, &sys->entity_ids, ecs->entity_count); - - sys->active = true; - sys->system_cb = system_cb; - sys->add_cb = add_cb; - sys->remove_cb = remove_cb; - sys->udata = udata; - - ecs->system_count++; - - return sys_id; -} - -void ecs_require_component(ecs_t* ecs, ecs_id_t sys_id, ecs_id_t comp_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_system_id(sys_id)); - ECS_ASSERT(ecs_is_valid_component_id(comp_id)); - ECS_ASSERT(ecs_is_system_ready(ecs, sys_id)); - ECS_ASSERT(ecs_is_component_ready(ecs, comp_id)); - - // Set system component bit for the specified component - ecs_sys_t* sys = &ecs->systems[sys_id]; - ecs_bitset_flip(&sys->require_bits, comp_id, true); -} - -void ecs_exclude_component(ecs_t* ecs, ecs_id_t sys_id, ecs_id_t comp_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_system_id(sys_id)); - ECS_ASSERT(ecs_is_valid_component_id(comp_id)); - ECS_ASSERT(ecs_is_system_ready(ecs, sys_id)); - ECS_ASSERT(ecs_is_component_ready(ecs, comp_id)); - - // Set system component bit for the specified component - ecs_sys_t* sys = &ecs->systems[sys_id]; - ecs_bitset_flip(&sys->exclude_bits, comp_id, true); -} - -void ecs_enable_system(ecs_t* ecs, ecs_id_t sys_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_system_id(sys_id)); - ECS_ASSERT(ecs_is_system_ready(ecs, sys_id)); - - ecs_sys_t* sys = &ecs->systems[sys_id]; - sys->active = true; -} - -void ecs_disable_system(ecs_t* ecs, ecs_id_t sys_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_system_id(sys_id)); - ECS_ASSERT(ecs_is_system_ready(ecs, sys_id)); - - ecs_sys_t* sys = &ecs->systems[sys_id]; - sys->active = false; -} - -ecs_id_t ecs_create(ecs_t* ecs) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - - ecs_stack_t* pool = &ecs->entity_pool; - - // If pool is empty, increase the number of entity IDs - if (0 == ecs_stack_size(pool)) - { - size_t old_count = ecs->entity_count; - size_t new_count = old_count + (old_count / 2) + 2; - - // Reallocates entities and zeros new ones - ecs->entities = (ecs_entity_t*)ecs_realloc_zero(ecs, ecs->entities, - old_count * sizeof(ecs_entity_t), - new_count * sizeof(ecs_entity_t)); - - // Push new entity IDs into the pool - for (ecs_id_t id = old_count; id < new_count; id++) - { - ecs_stack_push(ecs, pool, id); - } - - // Update entity count - ecs->entity_count = new_count; - } - - ecs_id_t entity_id = ecs_stack_pop(pool); - ecs->entities[entity_id].ready = true; - - return entity_id; -} - -bool ecs_is_ready(ecs_t* ecs, ecs_id_t entity_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - - return ecs->entities[entity_id].ready; -} - -void ecs_destroy(ecs_t* ecs, ecs_id_t entity_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - - // Load entity - ecs_entity_t* entity = &ecs->entities[entity_id]; - - // Remove entity from systems - for (ecs_id_t sys_id = 0; sys_id < ecs->system_count; sys_id++) - { - ecs_sys_t* sys = &ecs->systems[sys_id]; - - // Just attempting to remove the entity from the sparse set is faster - // than calling ecs_entity_system_test - if (ecs_sparse_set_remove(&sys->entity_ids, entity_id)) - { - if (sys->remove_cb) - sys->remove_cb(ecs, entity_id, sys->udata); - } - } - - // Push entity ID back into pool - ecs_stack_t* pool = &ecs->entity_pool; - ecs_stack_push(ecs, pool, entity_id); - - // Loop through components and call the destructors - for (ecs_id_t comp_id = 0; comp_id < ecs->comp_count; comp_id++) - { - if (ecs_bitset_test(&entity->comp_bits, comp_id)) - { - ecs_comp_t* comp = &ecs->comps[comp_id]; - - if (comp->destructor) - { - void* ptr = ecs_get(ecs, entity_id, comp_id); - comp->destructor(ecs, entity_id, ptr); - } - } - } - - // Reset entity (sets bitset to 0 and ready to false) - memset(entity, 0, sizeof(ecs_entity_t)); -} - -bool ecs_has(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_component_id(comp_id)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - - // Load entity - ecs_entity_t* entity = &ecs->entities[entity_id]; - - // Return true if the component belongs to the entity - return ecs_bitset_test(&entity->comp_bits, comp_id); -} - -void* ecs_get(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_component_id(comp_id)); - ECS_ASSERT(ecs_is_component_ready(ecs, comp_id)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - - // Return pointer to component - // eid0, eid1 eid2, ... - // [comp0, comp1, comp2, ...] - ecs_array_t* comp_array = &ecs->comp_arrays[comp_id]; - return (char*)comp_array->data + (comp_array->size * entity_id); -} - -void* ecs_add(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id, void* args) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_component_id(comp_id)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - ECS_ASSERT(ecs_is_component_ready(ecs, comp_id)); - - // Load entity - ecs_entity_t* entity = &ecs->entities[entity_id]; - - // Load component - ecs_array_t* comp_array = &ecs->comp_arrays[comp_id]; - ecs_comp_t* comp = &ecs->comps[comp_id]; - - // Grow the component array - ecs_array_resize(ecs, comp_array, entity_id); - - // Get pointer to component - void* ptr = ecs_get(ecs, entity_id, comp_id); - - // Call constructor - if (comp->constructor) - comp->constructor(ecs, entity_id, ptr, args); - else - memset(ptr, 0, comp_array->size); - - // Set entity component bit that determines which systems this entity - // belongs to - ecs_bitset_flip(&entity->comp_bits, comp_id, true); - - // Add entity to systems - for (ecs_id_t sys_id = 0; sys_id < ecs->system_count; sys_id++) - { - ecs_sys_t* sys = &ecs->systems[sys_id]; - - if (ecs_entity_system_test(&sys->require_bits, &sys->exclude_bits, &entity->comp_bits)) - { - if (ecs_sparse_set_add(ecs, &sys->entity_ids, entity_id)) - { - if (sys->add_cb) - sys->add_cb(ecs, entity_id, sys->udata); - } - } - } - - // Return component - return ptr; -} - -void ecs_remove(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_component_id(comp_id)); - ECS_ASSERT(ecs_is_component_ready(ecs, comp_id)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - - // Load entity - ecs_entity_t* entity = &ecs->entities[entity_id]; - - // Remove entity from systems - for (ecs_id_t sys_id = 0; sys_id < ecs->system_count; sys_id++) - { - ecs_sys_t* sys = &ecs->systems[sys_id]; - - if (ecs_entity_system_test(&sys->require_bits, &sys->exclude_bits, &entity->comp_bits)) - { - if (ecs_sparse_set_remove(&sys->entity_ids, entity_id)) - { - if (sys->remove_cb) - sys->remove_cb(ecs, entity_id, sys->udata); - } - } - } - - ecs_comp_t* comp = &ecs->comps[comp_id]; - - if (comp->destructor) - { - void* ptr = ecs_get(ecs, entity_id, comp_id); - comp->destructor(ecs, entity_id, ptr); - } - - // Reset the relevant component mask bit - ecs_bitset_flip(&entity->comp_bits, comp_id, false); -} - -void ecs_queue_destroy(ecs_t* ecs, ecs_id_t entity_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - - ecs_stack_push(ecs, &ecs->destroy_queue, entity_id); -} - -void ecs_queue_remove(ecs_t* ecs, ecs_id_t entity_id, ecs_id_t comp_id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_entity_ready(ecs, entity_id)); - ECS_ASSERT(ecs_has(ecs, entity_id, comp_id)); - - ecs_stack_push(ecs, &ecs->remove_queue, entity_id); - ecs_stack_push(ecs, &ecs->remove_queue, comp_id); -} - -ecs_ret_t ecs_update_system(ecs_t* ecs, ecs_id_t sys_id, ecs_dt_t dt) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_valid_system_id(sys_id)); - ECS_ASSERT(ecs_is_system_ready(ecs, sys_id)); - ECS_ASSERT(dt >= 0.0f); - - ecs_sys_t* sys = &ecs->systems[sys_id]; - - if (!sys->active) - return 0; - - ecs_ret_t code = sys->system_cb(ecs, - sys->entity_ids.dense, - sys->entity_ids.size, - dt, - sys->udata); - - ecs_flush_destroyed(ecs); - ecs_flush_removed(ecs); - - return code; -} - -ecs_ret_t ecs_update_systems(ecs_t* ecs, ecs_dt_t dt) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(dt >= 0.0f); - - for (ecs_id_t sys_id = 0; sys_id < ecs->system_count; sys_id++) - { - ecs_ret_t code = ecs_update_system(ecs, sys_id, dt); - - if (0 != code) - return code; - } - - return 0; -} - -/*============================================================================= -* Internal realloc wrapper -*============================================================================*/ -void* ecs_realloc_zero(ecs_t* ecs, void* ptr, size_t old_size, size_t new_size) -{ - (void)ecs; - - ptr = ECS_REALLOC(ptr, new_size, ecs->mem_ctx); - - if (new_size > old_size && ptr) { - size_t diff = new_size - old_size; - void* start = ((char*)ptr)+ old_size; - memset(start, 0, diff); - } - - return ptr; -} - -/*============================================================================= -* Internal functions to flush destroyed entity and removed component -*============================================================================*/ - -static void ecs_flush_destroyed(ecs_t* ecs) -{ - ecs_stack_t* destroy_queue = &ecs->destroy_queue; - - for (size_t i = 0; i < destroy_queue->size; i++) - { - ecs_id_t entity_id = destroy_queue->array[i]; - - if (ecs_is_ready(ecs, entity_id)) - ecs_destroy(ecs, entity_id); - } - - destroy_queue->size = 0; -} - -static void ecs_flush_removed(ecs_t* ecs) -{ - ecs_stack_t* remove_queue = &ecs->remove_queue; - - for (size_t i = 0; i < remove_queue->size; i += 2) - { - ecs_id_t entity_id = remove_queue->array[i]; - - if (ecs_is_ready(ecs, entity_id)) - { - ecs_id_t comp_id = remove_queue->array[i + 1]; - ecs_remove(ecs, entity_id, comp_id); - } - } - - remove_queue->size = 0; -} - - -/*============================================================================= -* Internal bitset functions -*============================================================================*/ - -#if ECS_MAX_COMPONENTS <= 64 - -static inline bool ecs_bitset_is_zero(ecs_bitset_t* set) -{ - return *set == 0; -} - -static inline void ecs_bitset_flip(ecs_bitset_t* set, int bit, bool on) -{ - if (on) - *set |= (1 << bit); - else - *set &= ~(1 << bit); -} - -static inline bool ecs_bitset_test(ecs_bitset_t* set, int bit) -{ - return *set & (1 << bit); -} - -static inline ecs_bitset_t ecs_bitset_and(ecs_bitset_t* set1, ecs_bitset_t* set2) -{ - return *set1 & *set2; -} - -static inline ecs_bitset_t ecs_bitset_or(ecs_bitset_t* set1, ecs_bitset_t* set2) -{ - return *set1 | *set2; -} - -static inline ecs_bitset_t ecs_bitset_not(ecs_bitset_t* set) -{ - return ~(*set); -} - -static inline bool ecs_bitset_equal(ecs_bitset_t* set1, ecs_bitset_t* set2) -{ - return *set1 == *set2; -} - -static inline bool ecs_bitset_true(ecs_bitset_t* set) -{ - return *set; -} - -#else // ECS_MAX_COMPONENTS - -static inline bool ecs_bitset_is_zero(ecs_bitset_t* set) -{ - for (int i = 0; i < ECS_BITSET_SIZE; i++) - { - if (set->array[i] != 0) - return false; - } - - return true; -} - -static inline void ecs_bitset_flip(ecs_bitset_t* set, int bit, bool on) -{ - int index = bit / ECS_BITSET_WIDTH; - - if (on) - set->array[index] |= (1 << bit % ECS_BITSET_WIDTH); - else - set->array[index] &= ~(1 << bit % ECS_BITSET_WIDTH); -} - -static inline bool ecs_bitset_test(ecs_bitset_t* set, int bit) -{ - int index = bit / ECS_BITSET_WIDTH; - return set->array[index] & (1 << bit % ECS_BITSET_WIDTH); -} - -static inline ecs_bitset_t ecs_bitset_and(ecs_bitset_t* set1, - ecs_bitset_t* set2) -{ - ecs_bitset_t set; - - for (int i = 0; i < ECS_BITSET_SIZE; i++) - { - set.array[i] = set1->array[i] & set2->array[i]; - } - - return set; -} - -static inline ecs_bitset_t ecs_bitset_or(ecs_bitset_t* set1, - ecs_bitset_t* set2) -{ - ecs_bitset_t set; - - for (int i = 0; i < ECS_BITSET_SIZE; i++) - { - set.array[i] = set1->array[i] | set2->array[i]; - } - - return set; -} - - -static inline ecs_bitset_t ecs_bitset_not(ecs_bitset_t* set) -{ - ecs_bitset_t out; - - for (int i = 0; i < ECS_BITSET_SIZE; i++) - { - out.array[i] = ~set->array[i]; - } - - return out; -} - -static inline bool ecs_bitset_equal(ecs_bitset_t* set1, ecs_bitset_t* set2) -{ - for (int i = 0; i < ECS_BITSET_SIZE; i++) - { - if (set1->array[i] != set2->array[i]) - { - return false; - } - } - - return true; -} - -static inline bool ecs_bitset_true(ecs_bitset_t* set) -{ - for (int i = 0; i < ECS_BITSET_SIZE; i++) - { - if (set->array[i]) - return true; - } - - return false; -} - -#endif // ECS_MAX_COMPONENTS - -/*============================================================================= -* Internal sparse set functions -*============================================================================*/ - -static void ecs_sparse_set_init(ecs_t* ecs, ecs_sparse_set_t* set, size_t capacity) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(set)); - ECS_ASSERT(capacity > 0); - - (void)ecs; - - set->capacity = capacity; - set->size = 0; - - set->dense = (ecs_id_t*)ECS_MALLOC(capacity * sizeof(ecs_id_t), ecs->mem_ctx); - set->sparse = (size_t*) ECS_MALLOC(capacity * sizeof(size_t), ecs->mem_ctx); - - memset(set->sparse, 0, capacity * sizeof(size_t)); -} - -static void ecs_sparse_set_free(ecs_t* ecs, ecs_sparse_set_t* set) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(set)); - - (void)ecs; - - ECS_FREE(set->dense, ecs->mem_ctx); - ECS_FREE(set->sparse, ecs->mem_ctx); -} - -static bool ecs_sparse_set_add(ecs_t* ecs, ecs_sparse_set_t* set, ecs_id_t id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(set)); - - (void)ecs; - - // Grow sparse set if necessary - if (id >= set->capacity) - { - size_t old_capacity = set->capacity; - size_t new_capacity = old_capacity; - - // Calculate new capacity - while (new_capacity <= id) - { - new_capacity += (new_capacity / 2) + 2; - } - - // Grow dense array - set->dense = (ecs_id_t*)ECS_REALLOC(set->dense, - new_capacity * sizeof(ecs_id_t), - ecs->mem_ctx); - - // Grow sparse array and zero it - set->sparse = (size_t*)ecs_realloc_zero(ecs, - set->sparse, - old_capacity * sizeof(size_t), - new_capacity * sizeof(size_t)); - - // Set the new capacity - set->capacity = new_capacity; - } - - // Check if ID exists within the set - if (ECS_NULL != ecs_sparse_set_find(set, id)) - return false; - - // Add ID to set - set->dense[set->size] = id; - set->sparse[id] = set->size; - - set->size++; - - return true; -} - -static size_t ecs_sparse_set_find(ecs_sparse_set_t* set, ecs_id_t id) -{ - ECS_ASSERT(ecs_is_not_null(set)); - - if (set->sparse[id] < set->size && set->dense[set->sparse[id]] == id) - return set->sparse[id]; - else - return ECS_NULL; -} - -static bool ecs_sparse_set_remove(ecs_sparse_set_t* set, ecs_id_t id) -{ - ECS_ASSERT(ecs_is_not_null(set)); - - if (ECS_NULL == ecs_sparse_set_find(set, id)) - return false; - - // Swap and remove (changes order of array) - ecs_id_t tmp = set->dense[set->size - 1]; - set->dense[set->sparse[id]] = tmp; - set->sparse[tmp] = set->sparse[id]; - - set->size--; - - return true; -} - -/*============================================================================= -* Internal system entity add/remove functions -*============================================================================*/ - -inline static bool ecs_entity_system_test(ecs_bitset_t* require_bits, - ecs_bitset_t* exclude_bits, - ecs_bitset_t* entity_bits) -{ - if (!ecs_bitset_is_zero(exclude_bits)) - { - ecs_bitset_t overlap = ecs_bitset_and(entity_bits, exclude_bits); - - if (ecs_bitset_true(&overlap)) - { - return false; - } - } - - ecs_bitset_t entity_and_require = ecs_bitset_and(entity_bits, require_bits); - return ecs_bitset_equal(&entity_and_require, require_bits); -} - -/*============================================================================= -* Internal ID pool functions -*============================================================================*/ - -inline static void ecs_stack_init(ecs_t* ecs, ecs_stack_t* stack, int capacity) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(stack)); - ECS_ASSERT(capacity > 0); - - (void)ecs; - - stack->size = 0; - stack->capacity = capacity; - stack->array = (ecs_id_t*)ECS_MALLOC(capacity * sizeof(ecs_id_t), ecs->mem_ctx); -} - -inline static void ecs_stack_free(ecs_t* ecs, ecs_stack_t* stack) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(stack)); - - (void)ecs; - - ECS_FREE(stack->array, ecs->mem_ctx); -} - -inline static void ecs_stack_push(ecs_t* ecs, ecs_stack_t* stack, ecs_id_t id) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(stack)); - ECS_ASSERT(stack->capacity > 0); - - (void)ecs; - - if (stack->size == stack->capacity) - { - stack->capacity += (stack->capacity / 2) + 2; - - stack->array = (ecs_id_t*)ECS_REALLOC(stack->array, - stack->capacity * sizeof(ecs_id_t), - ecs->mem_ctx); - } - - stack->array[stack->size++] = id; -} - -inline static ecs_id_t ecs_stack_pop(ecs_stack_t* stack) -{ - ECS_ASSERT(ecs_is_not_null(stack)); - return stack->array[--stack->size]; -} - -inline static int ecs_stack_size(ecs_stack_t* stack) -{ - return stack->size; -} - -static void ecs_array_init(ecs_t* ecs, ecs_array_t* array, size_t size, size_t capacity) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(array)); - - (void)ecs; - - memset(array, 0, sizeof(ecs_array_t)); - - array->capacity = capacity; - array->count = 0; - array->size = size; - array->data = ECS_MALLOC(size * capacity, ecs->mem_ctx); -} - -static void ecs_array_free(ecs_t* ecs, ecs_array_t* array) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(array)); - - (void)ecs; - - ECS_FREE(array->data, ecs->mem_ctx); -} - -static void ecs_array_resize(ecs_t* ecs, ecs_array_t* array, size_t capacity) -{ - ECS_ASSERT(ecs_is_not_null(ecs)); - ECS_ASSERT(ecs_is_not_null(array)); - - (void)ecs; - - if (capacity >= array->capacity) - { - while (array->capacity <= capacity) - { - array->capacity += (array->capacity / 2) + 2; - } - - array->data = ECS_REALLOC(array->data, - array->capacity * array->size, - ecs->mem_ctx); - } -} - -/*============================================================================= -* Internal validation functions -*============================================================================*/ -#ifndef NDEBUG -static bool ecs_is_not_null(void* ptr) -{ - return NULL != ptr; -} - -static bool ecs_is_valid_component_id(ecs_id_t id) -{ - return id < ECS_MAX_COMPONENTS; -} - -static bool ecs_is_valid_system_id(ecs_id_t id) -{ - return id < ECS_MAX_SYSTEMS; -} - -static bool ecs_is_entity_ready(ecs_t* ecs, ecs_id_t entity_id) -{ - return ecs->entities[entity_id].ready; -} - -static bool ecs_is_component_ready(ecs_t* ecs, ecs_id_t comp_id) -{ - return comp_id < ecs->comp_count; -} - -static bool ecs_is_system_ready(ecs_t* ecs, ecs_id_t sys_id) -{ - return sys_id < ecs->system_count; -} - -#endif // NDEBUG - -#endif // PICO_ECS_IMPLEMENTATION - -/* - ---------------------------------------------------------------------------- - This software is available under two licenses (A) or (B). You may choose - either one as you wish: - ---------------------------------------------------------------------------- - - (A) The zlib License - - Copyright (c) 2021 James McLean - - This software is provided 'as-is', without any express or implied warranty. - In no event will the authors be held liable for any damages arising from the - use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software in a - product, an acknowledgment in the product documentation would be appreciated - but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. - - ---------------------------------------------------------------------------- - - (B) Public Domain (www.unlicense.org) - - This is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or distribute - this software, either in source code form or as a compiled binary, for any - purpose, commercial or non-commercial, and by any means. - - In jurisdictions that recognize copyright laws, the author or authors of - this software dedicate any and all copyright interest in the software to the - public domain. We make this dedication for the benefit of the public at - large and to the detriment of our heirs and successors. We intend this - dedication to be an overt act of relinquishment in perpetuity of all present - and future rights to this software under copyright law. - - 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 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. -*/ - -// EoF diff --git a/plot.config.json b/plot.config.json index 37953d8..ff8e817 100644 --- a/plot.config.json +++ b/plot.config.json @@ -4,151 +4,433 @@ "index": "Update {:>5s} entities with 7 Systems", "title": "Update systems (7 systems, mixed components)", "regex": "^BM_(.*_)?ComplexSystemsUpdateMixedEntities\\/[0-9]+$", - "header": "Update systems (for-each entities (with mixed components) in 7 systems)" - }, - "ComplexSystemsUpdateNoEntities": { - "index": "Update 0 entities with 7 systems", - "title": "Update Systems (7 Systems) with zero entities", - "regex": "^BM_(.*_)?ComplexSystemsUpdate_NoEntities$", - "header": "Update systems (for-each entities in 7 systems) with zero entities" + "header": "Update systems (for-each entities (with mixed components) in 7 systems)", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "ComplexSystemsUpdate": { "index": "Update {:>5s} entities with 7 systems", "title": "Update Systems (7 Systems)", "regex": "^BM_(.*_)?ComplexSystemsUpdate\\/[0-9]+$", - "header": "Update systems (for-each entities in 7 systems)" + "header": "Update systems (for-each entities in 7 systems)", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "SystemsUpdateMixedEntities": { "index": "Update {:>5s} entities with 2 systems", "title": "Update systems (2 systems, mixed components)", "regex": "^BM_(.*_)?SystemsUpdateMixedEntities\\/[0-9]+$", - "header": "Update systems (for-each entities (with mixed components) in 2 systems)" - }, - "SystemsUpdateNoEntities": { - "index": "Update 0 entities with 2 systems", - "title": "Update systems (2 systems) with zero entities", - "regex": "^BM_(.*_)?SystemsUpdate_NoEntities$", - "header": "Update systems (for-each entities in 2 systems) with zero entities" + "header": "Update systems (for-each entities (with mixed components) in 2 systems)", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "SystemsUpdate": { "index": "Update {:>5s} entities with 2 systems", "title": "Update systems (2 systems)", "regex": "^BM_(.*_)?SystemsUpdate\\/[0-9]+$", - "header": "Update systems (for-each entities in 2 systems)" + "header": "Update systems (for-each entities in 2 systems)", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "CreateEntitiesInBulk": { "index": "Create {:>5s} entities with two components at once", "title": "Create entities at once", "regex": "^BM_(.*_)?CreateEntitiesInBulk\\/[0-9]+$", - "header": "Create entities at once" + "header": "Create entities at once", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "CreateEntities": { "index": "Create {:>5s} entities with two Components", "title": "Create entities", "regex": "^BM_(.*_)?CreateEntities\\/[0-9]+$", - "header": "Create entities" + "header": "Create entities", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "CreateEmptyEntitiesInBulk": { "index": "Create {:>5s} (empty) entities at once", "title": "Create (empty) entities at once", "regex": "^BM_(.*_)?CreateEmptyEntitiesInBulk\\/[0-9]+$", - "header": "Create empty entities at once" + "header": "Create empty entities at once", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "CreateNoEntities": { "index": "Create No entities", "title": "Create No entities", "regex": "^BM_(.*_)?CreateNoEntities$", - "header": "Create No entities" + "header": "Create No entities", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "CreateEmptyEntities": { "index": "Create {:>5s} (empty) entities", "title": "Create (empty) entities", "regex": "^BM_(.*_)?CreateEmptyEntities\\/", - "header": "Create empty entities" + "header": "Create empty entities", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "DestroyEntitiesInBulk": { "index": "Destroy {:>5s} entities with two components at once", "title": "Destroy entities at once", "regex": "^BM_(.*_)?DestroyEntitiesInBulk\\/", - "header": "Destroy entities at once" + "header": "Destroy entities at once", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "DestroyEntities": { "index": "Destroy {:>5s} entities with two components", "title": "Destroy entities", "regex": "^BM_(.*_)?DestroyEntities\\/[0-9]+$", - "header": "Destroy entities" + "header": "Destroy entities", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "UnpackNoComponent": { "index": "Get No component in {:>5s} entities", "title": "Get No component from Entity", "regex": "^BM_(.*_)?UnpackNoComponent\\/[0-9]+$", - "header": "Get No component from Entity" - }, - "UnpackOneComponentNoEntities": { - "index": "Unpack No entities (empty entities)", - "title": "Get component from No Entity", - "regex": "^BM_(.*_)?UnpackOneComponent_NoEntities$", - "header": "Get component from No Entity" + "header": "Get No component from Entity", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "UnpackOneComponent": { "index": "Unpack one component in {:>5s} entities", "title": "Get one component from Entity", "regex": "^BM_(.*_)?UnpackOneComponent\\/[0-9]+$", - "header": "Get one (non-const) component from Entity" + "header": "Get one (non-const) component from Entity", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "UnpackTwoComponentsFromMixedEntities": { "index": "Unpack two components in {:>5s} entities", "title": "Get two components from entity", "regex": "^BM_(.*_)?UnpackTwoComponentsFromMixedEntities\\/[0-9]+$", - "header": "Get two components from entity" + "header": "Get two components from entity", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "UnpackTwoComponents": { "index": "Unpack two components in {:>5s} entities", "title": "Get two components from entity", "regex": "^BM_(.*_)?UnpackTwoComponents\\/[0-9]+$", - "header": "Get two components from entity" + "header": "Get two components from entity", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "UnpackThreeComponentsFromMixedEntities": { "index": "Unpack three components in {:>5s} entities", "title": "Get three components from Entity", "regex": "^BM_(.*_)?UnpackThreeComponentsFromMixedEntities\\/[0-9]+$", - "header": "Get three components from entity" + "header": "Get three components from entity", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "UnpackThreeComponents": { "index": "Unpack three components in {:>5s} entities", "title": "Get three components from Entity", "regex": "^BM_(.*_)?UnpackThreeComponents\\/[0-9]+$", - "header": "Get three components from entity" + "header": "Get three components from entity", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "RemoveAddComponent": { "index": "Remove and Add a Component in {:>5s} entities", "title": "Remove and add component from Entity", "regex": "^BM_(.*_)?RemoveAddComponent\\/[0-9]+$", - "header": "Remove and add component" + "header": "Remove and add component", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } + }, + "AddComponent": { + "index": "Add a Component in {:>5s} entities", + "title": "Add component from Entity", + "regex": "^BM_(.*_)?AddComponent\\/[0-9]+$", + "header": "Add component", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "IterateSingleComponent": { "index": "Iterate over {:>5s} entities with one component", "title": "Iterate over entities with one component", "regex": "^BM_(.*_)?IterateSingleComponent\\/[0-9]+$", - "header": "Iterate over entities with one component" + "header": "Iterate over entities with one component", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "IterateTwoComponents": { "index": "Iterate over {:>5s} entities with two components", "title": "Iterate over entities with two components", "regex": "^BM_(.*_)?IterateTwoComponents\\/[0-9]+$", - "header": "Iterate over entities with two components" + "header": "Iterate over entities with two components", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "IterateThreeComponentsWithMixedEntities": { "index": "Iterate over {:>5s} entities with three components", "title": "Iterate over entities with three components", "regex": "^BM_(.*_)?IterateThreeComponentsWithMixedEntities\\/[0-9]+$", - "header": "Iterate over entities with three components" + "header": "Iterate over entities with three components", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } }, "IterateThreeComponents": { "index": "Iterate over {:>5s} entities with three components", "title": "Iterate over entities with three components", "regex": "^BM_(.*_)?IterateThreeComponents\\/[0-9]+$", - "header": "Iterate over entities with three components" + "header": "Iterate over entities with three components", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per entity" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all entities" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per entity" + } + }, + "PublishAndUpdateEvents": { + "index": "Publish and Update {:>5s} events with three components", + "title": "Publish and Update events with three components", + "regex": "^BM_(.*_)?(EnqueueAndUpdateEvents.+|PublishAndUpdateEvents.+|EmitAndUpdateEvents.+|TriggerAndUpdateEvents.+)WithMixedEntities\\/[0-9]+$", + "header": "Publish and Update events with three components", + "line": { + "xaxis_title": "Entities", + "yaxis_title": "Time cost per event" + }, + "line2": { + "xaxis_title": "Entities", + "yaxis_title": "Time for all events" + }, + "histogram": { + "xaxis_title": "Entities (avg)", + "yaxis_title": "Time cost per event" + } } }, "frameworks": { @@ -164,7 +446,7 @@ "name": "EnTT", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "color": "#0033cc" }, @@ -172,7 +454,7 @@ "name": "EnTT (runtime)", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "skip_candidate": true, "color": "#66ccff" @@ -181,7 +463,7 @@ "name": "EnTT (group)", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "skip_candidate": true, "color": "#0099ff" @@ -190,7 +472,7 @@ "name": "EnTT (non-owning group)", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "skip_candidate": true, "color": "#00ccff" @@ -199,7 +481,7 @@ "name": "EnTT (full-owning group)", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "skip_candidate": true, "color": "#0099cc" @@ -208,19 +490,55 @@ "name": "EnTT (partial-owning group)", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "skip_candidate": true, "color": "#3366cc" }, + "entt (event)": { + "name": "EnTT (events)", + "author": "@skypjack", + "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", + "version": "v3.13.2", + "link": "https://github.com/skypjack/entt", + "skip_candidate": true, + "color": "#0033cc" + }, + "entt (component)": { + "name": "EnTT (component)", + "author": "@skypjack", + "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", + "version": "v3.13.2", + "link": "https://github.com/skypjack/entt", + "skip_candidate": true, + "color": "#66ccff" + }, + "entt (emit)": { + "name": "EnTT (emit)", + "author": "@skypjack", + "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", + "version": "v3.13.2", + "link": "https://github.com/skypjack/entt", + "skip_candidate": true, + "color": "#0099ff" + }, + "entt (emit, stable)": { + "name": "EnTT (emit, stable)", + "author": "@skypjack", + "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", + "version": "v3.13.2", + "link": "https://github.com/skypjack/entt", + "skip_candidate": true, + "color": "#3994d1" + }, "entt (stable)": { - "name": "EnTT (stable)", + "name": "EnTT (emit, stable)", "author": "@skypjack", "description": "EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.", - "version": "v3.13.1", + "version": "v3.13.2", "link": "https://github.com/skypjack/entt", "skip_candidate": true, - "color": "#336699" + "color": "#3994d1" }, "ginseng": { "name": "Ginseng", @@ -238,6 +556,15 @@ "link": "https://github.com/kirillochnev/mustache", "color": "#ff66cc" }, + "mustache (event)": { + "name": "mustache", + "author": "@kirillochnev", + "description": "A fast, modern C++ Entity Component System", + "version": "0.2 (Feb 2024)", + "link": "https://github.com/kirillochnev/mustache", + "skip_candidate": true, + "color": "#ff66cc" + }, "openecs": { "name": "OpenEcs", "author": "@Gronis", @@ -250,10 +577,19 @@ "name": "Flecs", "author": "@SanderMertens", "description": "Flecs is a fast and lightweight Entity Component System that lets you build games and simulations with millions of entities.", - "version": "v3.2.11", + "version": "v4.0.0", "link": "https://github.com/SanderMertens/flecs", "color": "#ff3300" }, + "flecs (emit)": { + "name": "Flecs (emit)", + "author": "@SanderMertens", + "description": "Flecs is a fast and lightweight Entity Component System that lets you build games and simulations with millions of entities.", + "version": "v4.0.0", + "link": "https://github.com/SanderMertens/flecs", + "skip_candidate": true, + "color": "#ff6c47" + }, "pico_ecs": { "name": "pico_ecs", "author": "@empyreanx", @@ -266,7 +602,7 @@ "name": "gaia-ecs", "author": "@richardbiely", "description": "Gaia-ECS is a fast and easy-to-use ECS framework.", - "version": "v0.8.4", + "version": "v0.8.6", "link": "https://github.com/richardbiely/gaia-ecs", "color": "#33a02c" }, @@ -274,7 +610,7 @@ "name": "gaia-ecs (SoA)", "author": "@richardbiely", "description": "Gaia-ECS is a fast and easy-to-use ECS framework.", - "version": "v0.8.4", + "version": "v0.8.6", "link": "https://github.com/richardbiely/gaia-ecs", "skip_candidate": true, "color": "#b2df8a" diff --git a/scripts/gen-benchmark-report/gen_benchmark_report/core.py b/scripts/gen-benchmark-report/gen_benchmark_report/core.py index a6b6a72..eefefa6 100755 --- a/scripts/gen-benchmark-report/gen_benchmark_report/core.py +++ b/scripts/gen-benchmark-report/gen_benchmark_report/core.py @@ -11,6 +11,7 @@ import json import re import pprint +import numpy as np RESULTS_MD_MUSTACHE_FILENAME = os.path.join(os.path.dirname(__file__), 'RESULTS.md.mustache') @@ -108,9 +109,11 @@ def gen_results(config, output_dir, reports): time_min = time_s / 60.0 key = None + plot_config_data = None for k, data in config['data'].items(): if re.search(data['regex'], name): key = k + plot_config_data = data break if not key: print("WARN: can find key for {:s}".format(name)) @@ -134,7 +137,8 @@ def gen_results(config, output_dir, reports): 'time_min': time_min, 'entities': entities, 'components_one': components_one, 'components_two': components_two, 'components_three': components_three, - 'output_image_filename': output_image_filename, 'line_output_image_filename': line_output_image_filename}) + 'output_image_filename': output_image_filename, 'line_output_image_filename': line_output_image_filename, + 'plot_config_data': plot_config_data}) result_plot_data = {} for k in entries.keys(): @@ -145,7 +149,7 @@ def gen_results(config, output_dir, reports): name = frameworks_info[framework]['name'] results[framework] = {'entries': entries, 'entries_data': entries_data, 'plot_data': result_plot_data, 'unit': entries_unit, 'framework': framework, - 'label': name, 'version': version} + 'label': name, 'version': version, 'plot_config_data': plot_config_data} results['_meta'] = {'ghz_per_cpu': mhz_per_cpu / 1000.0, 'mhz_per_cpu': mhz_per_cpu, 'num_cpus': num_cpus, 'os': platform.system(), 'ram': get_total_memory()} @@ -265,6 +269,7 @@ def gen_results(config, output_dir, reports): output_image_filename = result['entries_data'][ek][0]['output_image_filename'] line_output_image_filename = result['entries_data'][ek][0]['line_output_image_filename'] name = frameworks_info[framework]['name'] + plot_config_data = result['plot_config_data'] if ek not in results['_data_frame_data']: results['_data_frame_data'][ek] = {} @@ -306,8 +311,8 @@ def gen_results(config, output_dir, reports): results['_data_frame_data'][ek]['unit'] = unit results['_data_frame_data'][ek]['name'] = name results['_data_frame_data'][ek]['y'].append(name) - results['_data_frame_data'][ek]['xaxis_title'] = 'Entities' - results['_data_frame_data'][ek]['yaxis_title'] = 'Time cost per entity' + results['_data_frame_data'][ek]['xaxis_title'] = plot_config_data['line']['xaxis_title'] if plot_config_data and 'line' in plot_config_data else 'Entities' + results['_data_frame_data'][ek]['yaxis_title'] = plot_config_data['line']['yaxis_title'] if plot_config_data and 'line' in plot_config_data else 'Time cost per entity' ## frame for second line graph results['_plot_data_line'][ek]['df'][name] = y_absolut results['_plot_data_line'][ek]['df']['entities'] = x @@ -316,8 +321,8 @@ def gen_results(config, output_dir, reports): results['_plot_data_line'][ek]['unit'] = unit results['_plot_data_line'][ek]['name'] = name results['_plot_data_line'][ek]['y'].append(name) - results['_plot_data_line'][ek]['xaxis_title'] = 'Entities' - results['_plot_data_line'][ek]['yaxis_title'] = 'Time for all entities' + results['_plot_data_line'][ek]['xaxis_title'] = plot_config_data['line2']['xaxis_title'] if plot_config_data and 'line2' in plot_config_data else 'Entities' + results['_plot_data_line'][ek]['yaxis_title'] = plot_config_data['line2']['yaxis_title'] if plot_config_data and 'line2' in plot_config_data else 'Time for all entities' ## frame data for histogram results['_plot_data_histogram'][ek]['data']['Framework'] = results['_plot_data_histogram'][ek]['data']['Framework'] + histo_frameworks @@ -330,8 +335,8 @@ def gen_results(config, output_dir, reports): results['_plot_data_histogram'][ek]['barmode'] = 'group' results['_plot_data_histogram'][ek]['histfunc'] = 'avg' results['_plot_data_histogram'][ek]['labels'] = {'Time': "Time ({})".format(unit), 'Entities': 'Entities', 'EntityGroup': 'Entities'} - results['_plot_data_histogram'][ek]['xaxis_title'] = 'Entities (avg)' - results['_plot_data_histogram'][ek]['yaxis_title'] = 'Time cost per entity' + results['_plot_data_histogram'][ek]['xaxis_title'] = plot_config_data['histogram']['xaxis_title'] if plot_config_data and 'histogram' in plot_config_data else 'Entities (avg)' + results['_plot_data_histogram'][ek]['yaxis_title'] = plot_config_data['histogram']['yaxis_title'] if plot_config_data and 'histogram' in plot_config_data else 'Time cost per entity' results['_plot_data_histogram'][ek]['output_image_filename'] = output_image_filename results['_plot_data_histogram'][ek]['unit'] = unit @@ -364,6 +369,7 @@ def gen_results(config, output_dir, reports): # Create a new column 'EntityGroup' based on the custom groups results['_plot_data_histogram'][ek]['data']['EntityGroup'] = pd.cut(results['_plot_data_histogram'][ek]['data']['Entities'], bins=list(custom_groups.keys()) + [float('inf')], labels=list(custom_groups.values())) results['_plot_data_histogram'][ek]['data_frame'] = pd.DataFrame(results['_plot_data_histogram'][ek]['data']) + results['_plot_data_histogram'][ek]['df'] = results['_plot_data_histogram'][ek]['data_frame'] return results @@ -405,6 +411,14 @@ def gen_plots(config, results): if 'color' in framework: color_discrete_map[framework['name']] = framework['color'] + frame_data_sizes = [] + for key, data in results['_data_frame_data'].items(): + for df_key, df_data in results['_data_frame_data'][key]['df'].items(): + frame_data_sizes.append(len(results['_data_frame_data'][key]['df']['entities'])) + for df_key, df_data in results['_plot_data_line'][key]['df'].items(): + frame_data_sizes.append(len(results['_plot_data_line'][key]['df']['entities'])) + frame_data_size = min(frame_data_sizes) + for key, data in results['_data_frame_data'].items(): title = config['data'][key]['title'] if not title: @@ -419,6 +433,11 @@ def gen_plots(config, results): fig.write_image(file=data['output_image_filename'], format=None, width=GEN_PLOT_IMAGE_WIDTH, height=GEN_PLOT_IMAGE_HEIGHT) print("INFO: gen line plot '{:s}': {:s}".format(title, data['output_image_filename'])) else: + for df_key, df_data in results['_data_frame_data'][key]['df'].items(): + results['_data_frame_data'][key]['df'][df_key] = results['_data_frame_data'][key]['df'][df_key][:frame_data_size] + for df_key, df_data in results['_plot_data_line'][key]['df'].items(): + results['_plot_data_line'][key]['df'][df_key] = results['_plot_data_line'][key]['df'][df_key][:frame_data_size] + ## line graph fig_lines = px.line(results['_plot_data_line'][key]['df'], x='entities', y=results['_plot_data_line'][key]['y'], labels={ "value": "Time ({})".format(results['_plot_data_line'][key]['unit']), @@ -694,19 +713,22 @@ def gen_results_md(config, output_dir, results_filename, results, img_dir): 'figure_img_alt': "{:s} Plot".format(ek), 'line_figure_img_src': os.path.join(img_dir, "{:s}.{:s}".format(ek, OUTPUT_IMG_FILENAME_EXT)), 'line_figure_img_alt': "{:s} Plot".format(ek), - 'key': ek, 'header': config_data[ek]['header'], 'title': config_data[ek]['title']} + 'key': ek, 'header': config_data[ek]['header'], 'title': config_data[ek]['title'], + 'line': config_data[ek]['line'], 'line2': config_data[ek]['line2'], 'histogram': config_data[ek]['histogram']} for ek in small_df_data.keys(): data['plots'][ek] = {'figure_img_src': os.path.join(img_dir, "{:s}.{:s}".format(ek, OUTPUT_IMG_FILENAME_EXT)), 'figure_img_alt': "{:s} Plot".format(ek), 'line_figure_img_src': os.path.join(img_dir, "Line{:s}.{:s}".format(ek, OUTPUT_IMG_FILENAME_EXT)), 'line_figure_img_alt': "{:s} Line Plot".format(ek), - 'key': ek, 'header': config_data[ek]['header'], 'title': config_data[ek]['title']} + 'key': ek, 'header': config_data[ek]['header'], 'title': config_data[ek]['title'], + 'line': config_data[ek]['line'], 'line2': config_data[ek]['line2'], 'histogram': config_data[ek]['histogram']} for ek in smaller_df_data.keys(): data['plots'][ek] = {'figure_img_src': os.path.join(img_dir, "{:s}.{:s}".format(ek, OUTPUT_IMG_FILENAME_EXT)), 'figure_img_alt': "{:s} Plot".format(ek), 'line_figure_img_src': os.path.join(img_dir, "Line{:s}.{:s}".format(ek, OUTPUT_IMG_FILENAME_EXT)), 'line_figure_img_alt': "{:s} Line Plot".format(ek), - 'key': ek, 'header': config_data[ek]['header'], 'title': config_data[ek]['title']} + 'key': ek, 'header': config_data[ek]['header'], 'title': config_data[ek]['title'], + 'line': config_data[ek]['line'], 'line2': config_data[ek]['line2'], 'histogram': config_data[ek]['histogram']} for ek, dfd in df_data.items(): df = None diff --git a/src/base/base/components/EmptyComponent.h b/src/base/base/components/EmptyComponent.h new file mode 100644 index 0000000..1dda5e4 --- /dev/null +++ b/src/base/base/components/EmptyComponent.h @@ -0,0 +1,12 @@ +#ifndef ECS_BENCHMARKS_BASE_COMPONENTS_EMPTYCOMPONENT_H_ +#define ECS_BENCHMARKS_BASE_COMPONENTS_EMPTYCOMPONENT_H_ + +#include + +namespace ecs::benchmarks::base::components { + +struct EmptyComponent{}; + +} // namespace ecs::benchmarks::base::components + +#endif \ No newline at end of file diff --git a/src/base/base/systems/MovementSystem.h b/src/base/base/systems/MovementSystem.h index fafeafd..125af6f 100644 --- a/src/base/base/systems/MovementSystem.h +++ b/src/base/base/systems/MovementSystem.h @@ -19,8 +19,8 @@ class MovementSystem : public System { static void updatePosition(ecs::benchmarks::base::components::PositionComponent& position, const ecs::benchmarks::base::components::VelocityComponent& direction, TimeDelta dt) { - position.x += direction.x * dt; - position.y += direction.y * dt; + position.x += direction.x * static_cast(dt); + position.y += direction.y * static_cast(dt); } }; diff --git a/src/entt/CMakeLists.txt b/src/entt/CMakeLists.txt index 754ef10..c6fd43e 100755 --- a/src/entt/CMakeLists.txt +++ b/src/entt/CMakeLists.txt @@ -3,7 +3,7 @@ cpmaddpackage( NAME EnTT VERSION - 3.13.1 + 3.13.2 GITHUB_REPOSITORY skypjack/entt OPTIONS diff --git a/src/entt/entt/entities/EntityFactory.h b/src/entt/entt/entities/EntityFactory.h index 9498f3b..3ecbe44 100644 --- a/src/entt/entt/entities/EntityFactory.h +++ b/src/entt/entt/entities/EntityFactory.h @@ -4,6 +4,7 @@ #include "entt/entt.h" #include "base/components/DataComponent.h" +#include "base/components/EmptyComponent.h" #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" #include "base/entities/EntityFactory.h" @@ -78,6 +79,19 @@ class EntityFactory { static inline auto& addComponentOne(EntityManager& registry, Entity entity) { return registry.emplace(entity); } + static inline auto& addComponentTwo(EntityManager& registry, Entity entity) { + return registry.emplace(entity); + } + static inline auto& addComponentThree(EntityManager& registry, Entity entity) { + return registry.emplace(entity); + } + + static inline void addComponentEmpty(EntityManager& registry, Entity entity) { + return registry.emplace(entity); + } + static inline void clearComponentsEmpty(EntityManager& registry) { + return registry.clear(); + } }; } // namespace ecs::benchmarks::entt::entities diff --git a/src/flecs/CMakeLists.txt b/src/flecs/CMakeLists.txt index 80fcdb3..0c4df96 100755 --- a/src/flecs/CMakeLists.txt +++ b/src/flecs/CMakeLists.txt @@ -3,7 +3,7 @@ cpmaddpackage( NAME flecs VERSION - 3.2.11 + 4.0.0 GITHUB_REPOSITORY SanderMertens/flecs OPTIONS diff --git a/src/flecs/flecs/FlecsApplication.h b/src/flecs/flecs/FlecsApplication.h index 82fe84c..b1bb225 100644 --- a/src/flecs/flecs/FlecsApplication.h +++ b/src/flecs/flecs/FlecsApplication.h @@ -40,8 +40,8 @@ class FlecsApplication { m_world .system() - .iter(systems::MovementSystem::update); - m_world.system().iter(systems::DataSystem::update); + .run(systems::MovementSystem::update); + m_world.system().run(systems::DataSystem::update); if (m_addMoreComplexSystem == base::add_more_complex_system_t::UseMoreComplexSystems) { m_world .system(); entity.add(); entity.add(); - entity.add(); - if (!entity.has()) { - entity.add(); + if (!entity.has()) { + entity.add(); } } diff --git a/src/flecs/flecs/systems/DataSystem.h b/src/flecs/flecs/systems/DataSystem.h index f124b34..d9ba273 100644 --- a/src/flecs/flecs/systems/DataSystem.h +++ b/src/flecs/flecs/systems/DataSystem.h @@ -15,11 +15,14 @@ class DataSystem { using EntityManager = ::flecs::world; using BaseSystem = ecs::benchmarks::base::systems::DataSystem; - inline static const auto update = [](::flecs::iter& it, ecs::benchmarks::base::components::DataComponent* data) { + inline static const auto update = [](::flecs::iter& it) { const auto dt = gsl::narrow_cast(it.delta_time()); - for (auto i : it) { - BaseSystem::updateData(data[i], dt); + while (it.next()) { + auto data = it.field(0); + for (auto i : it) { + BaseSystem::updateData(data[i], dt); + } } }; }; diff --git a/src/flecs/flecs/systems/MovementSystem.h b/src/flecs/flecs/systems/MovementSystem.h index 91176a4..dd1580d 100644 --- a/src/flecs/flecs/systems/MovementSystem.h +++ b/src/flecs/flecs/systems/MovementSystem.h @@ -15,13 +15,15 @@ class MovementSystem { using EntityManager = ::flecs::world; using BaseSystem = ecs::benchmarks::base::systems::MovementSystem; - inline static const auto update = [](::flecs::iter& it, - ecs::benchmarks::base::components::PositionComponent* position, - const ecs::benchmarks::base::components::VelocityComponent* direction) { + inline static const auto update = [](::flecs::iter& it) { const auto dt = gsl::narrow_cast(it.delta_time()); - for (auto i : it) { - BaseSystem::updatePosition(position[i], direction[i], dt); + while (it.next()) { + auto position = it.field(0); + const auto direction = it.field(1); + for (auto i : it) { + BaseSystem::updatePosition(position[i], direction[i], dt); + } } }; }; diff --git a/src/gaia-ecs/CMakeLists.txt b/src/gaia-ecs/CMakeLists.txt index a567962..84e2795 100755 --- a/src/gaia-ecs/CMakeLists.txt +++ b/src/gaia-ecs/CMakeLists.txt @@ -3,12 +3,9 @@ cpmaddpackage( NAME gaia VERSION - 0.8.5 + 0.8.6 GITHUB_REPOSITORY richardbiely/gaia-ecs - # TODO: set current version, use main for build fixes - GIT_TAG - main OPTIONS "GAIA_BUILD_UNITTEST OFF" "GAIA_BUILD_BENCHMARK OFF" diff --git a/src/gaia-ecs/gaia-ecs/GaiaEcsApplication.h b/src/gaia-ecs/gaia-ecs/GaiaEcsApplication.h index ccb3304..51b9e21 100644 --- a/src/gaia-ecs/gaia-ecs/GaiaEcsApplication.h +++ b/src/gaia-ecs/gaia-ecs/GaiaEcsApplication.h @@ -33,8 +33,8 @@ class GaiaEcsApplication { ~GaiaEcsApplication() = default; GaiaEcsApplication(const GaiaEcsApplication&) = delete; GaiaEcsApplication& operator=(const GaiaEcsApplication&) = delete; - GaiaEcsApplication(GaiaEcsApplication&&) = default; - GaiaEcsApplication& operator=(GaiaEcsApplication&&) = default; + GaiaEcsApplication(GaiaEcsApplication&&) = delete; + GaiaEcsApplication& operator=(GaiaEcsApplication&&) = delete; [[nodiscard]] inline EntityManager& getEntities() { return m_world; } [[nodiscard]] inline const EntityManager& getEntities() const { return m_world; } diff --git a/src/gaia-ecs/gaia-ecs/SoAGaiaEcsApplication.h b/src/gaia-ecs/gaia-ecs/SoAGaiaEcsApplication.h index 60b51aa..c150af5 100644 --- a/src/gaia-ecs/gaia-ecs/SoAGaiaEcsApplication.h +++ b/src/gaia-ecs/gaia-ecs/SoAGaiaEcsApplication.h @@ -33,8 +33,8 @@ class SoAGaiaEcsApplication { ~SoAGaiaEcsApplication() = default; SoAGaiaEcsApplication(const SoAGaiaEcsApplication&) = delete; SoAGaiaEcsApplication& operator=(const SoAGaiaEcsApplication&) = delete; - SoAGaiaEcsApplication(SoAGaiaEcsApplication&&) = default; - SoAGaiaEcsApplication& operator=(SoAGaiaEcsApplication&&) = default; + SoAGaiaEcsApplication(SoAGaiaEcsApplication&&) = delete; + SoAGaiaEcsApplication& operator=(SoAGaiaEcsApplication&&) = delete; [[nodiscard]] inline EntityManager& getEntities() { return m_world; } [[nodiscard]] inline const EntityManager& getEntities() const { return m_world; } diff --git a/src/gaia-ecs/gaia-ecs/entities/EntityFactory.cpp b/src/gaia-ecs/gaia-ecs/entities/EntityFactory.cpp index fb3c4a7..4d11d1f 100644 --- a/src/gaia-ecs/gaia-ecs/entities/EntityFactory.cpp +++ b/src/gaia-ecs/gaia-ecs/entities/EntityFactory.cpp @@ -10,31 +10,64 @@ EntityFactory::Entity EntityFactory::createEmpty(EntityManager& entities) { return entities.add(); } +void EntityFactory::createEmptyBulk(EntityManager& entities, size_t nentities) { + entities.add_n(static_cast(nentities)); +} + EntityFactory::Entity EntityFactory::createSingle(EntityManager& entities) { auto e = entities.add(); entities.add(e); return e; } +void EntityFactory::createSingleBulk(EntityManager& entities, size_t nentities) { + auto e = entities.add(); + entities.add(e); + entities.add_n(e, static_cast(nentities-1U)); +} + EntityFactory::Entity EntityFactory::create(EntityManager& entities) { auto e = entities.add(); - entities.bulk(e) + entities.build(e) .add() .add() .add(); return e; } +void EntityFactory::createBulk(EntityManager& entities, size_t nentities) { + auto e = entities.add(); + entities.build(e) + .add() + .add() + .add(); + entities.add_n(e, static_cast(nentities-1U)); +} + EntityFactory::Entity EntityFactory::createMinimal(EntityManager& entities) { auto e = entities.add(); - entities.bulk(e) + entities.build(e) .add() .add(); return e; } +void EntityFactory::createMinimalBulk(EntityManager& entities, size_t nentities) { + auto e = entities.add(); + entities.build(e) + .add() + .add(); + entities.add_n(e, static_cast(nentities-1U)); +} + void EntityFactory::destroy(EntityManager& entities, Entity entity) { entities.del(entity); } +void EntityFactory::destroyBulk(EntityManager& entities, std::vector& entities_vec) { + for (auto entity : entities_vec) { + entities.del(entity); + } +} + } // namespace ecs::benchmarks::gaia_ecs::entities diff --git a/src/gaia-ecs/gaia-ecs/entities/EntityFactory.h b/src/gaia-ecs/gaia-ecs/entities/EntityFactory.h index fb929fc..46edd0b 100644 --- a/src/gaia-ecs/gaia-ecs/entities/EntityFactory.h +++ b/src/gaia-ecs/gaia-ecs/entities/EntityFactory.h @@ -5,7 +5,6 @@ #include "base/components/PositionComponent.h" #include "base/components/VelocityComponent.h" #include -#include namespace ecs::benchmarks::gaia_ecs::entities { @@ -15,18 +14,25 @@ class EntityFactory { using Entity = ::gaia::ecs::Entity; static Entity createEmpty(EntityManager& entities); + static void createEmptyBulk(EntityManager& entities, size_t nentities); static Entity createSingle(EntityManager& entities); + static void createSingleBulk(EntityManager& entities, size_t nentities); static Entity create(EntityManager& entities); + static void createBulk(EntityManager& entities, size_t nentities); static Entity createMinimal(EntityManager& entities); + static void createMinimalBulk(EntityManager& entities, size_t nentities); static void destroy(EntityManager& entities, Entity entity); + static void destroyBulk(EntityManager& entities, std::vector& entities_vec); - //[[nodiscard]] static inline auto getEntitiesCount(EntityManager& entities) { - // return entities.size(); - //} + template + [[nodiscard]] static inline auto getComponentCount(EntityManager& entities) { + auto query = entities.query().all(); + return query.count(); + } [[nodiscard]] static inline const ecs::benchmarks::base::components::PositionComponent& getComponentOneConst(EntityManager& entities, Entity entity) { diff --git a/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.cpp b/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.cpp index c631846..6d8f539 100644 --- a/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.cpp +++ b/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.cpp @@ -6,7 +6,7 @@ namespace ecs::benchmarks::gaia_ecs::entities { HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityManager& entities) { using namespace ecs::benchmarks::base::components; auto ret = entities.add(); - entities.bulk(ret) + entities.build(ret) .add() .add() .add() @@ -18,7 +18,7 @@ HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createRandom(EntityMa HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityManager& entities) { using namespace ecs::benchmarks::base::components; auto ret = entities.add(); - entities.bulk(ret) + entities.build(ret) .add() .add() .add() @@ -30,7 +30,7 @@ HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createHero(EntityMana HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityManager& entities) { using namespace ecs::benchmarks::base::components; auto ret = entities.add(); - entities.bulk(ret) + entities.build(ret) .add() .add() .add() @@ -41,12 +41,17 @@ HeroMonsterEntityFactory::Entity HeroMonsterEntityFactory::createMonster(EntityM } void HeroMonsterEntityFactory::addComponents(EntityManager& entities, Entity entity) { - entities.bulk(entity) + auto builder = entities.build(entity); + builder .add() .add() .add() - .add() .add(); + if (!entities.has(entity)) { + builder.add(); + } + builder.commit(); + } } // namespace ecs::benchmarks::gaia_ecs::entities \ No newline at end of file diff --git a/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.h b/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.h index 065d85e..cb87878 100644 --- a/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.h +++ b/src/gaia-ecs/gaia-ecs/entities/HeroMonsterEntityFactory.h @@ -9,71 +9,57 @@ namespace ecs::benchmarks::gaia_ecs::entities { -class HeroMonsterEntityFactory { +class HeroMonsterEntityFactory final + : public ecs::benchmarks::base::entities::HeroMonsterEntityFactory< + ::gaia::ecs::World, ::gaia::ecs::Entity, ecs::benchmarks::base::components::PositionComponent, + ecs::benchmarks::base::components::PlayerComponent, ecs::benchmarks::base::components::HealthComponent, + ecs::benchmarks::base::components::DamageComponent, ecs::benchmarks::base::components::SpriteComponent> { public: - using EntityManager = ::gaia::ecs::World; - using Entity = ::gaia::ecs::Entity; - using BaseHeroMonsterEntityFactory = ecs::benchmarks::base::entities::HeroMonsterEntityFactory< - EntityManager, Entity, ecs::benchmarks::base::components::PositionComponent, - ecs::benchmarks::base::components::PlayerComponent, ecs::benchmarks::base::components::HealthComponent, - ecs::benchmarks::base::components::DamageComponent, ecs::benchmarks::base::components::SpriteComponent>; + // using EntityManager = ::gaia::ecs::World; + // using Entity = ::gaia::ecs::Entity; + + Entity createRandom(EntityManager& entities) override; + Entity createHero(EntityManager& entities) override; + Entity createMonster(EntityManager& entities) override; - Entity createRandom(EntityManager& entities); - Entity createHero(EntityManager& entities); - Entity createMonster(EntityManager& entities); + [[nodiscard]] static inline bool valid(EntityManager& entities, Entity entity) { return entities.valid(entity); } - void addComponents(EntityManager& entities, Entity entity); + void addComponents(EntityManager& entities, Entity entity) override; - //[[nodiscard]] static inline auto getEntitiesCount(EntityManager& entities) { - // return entities.size(); - //} - - [[nodiscard]] inline const ecs::benchmarks::base::components::PositionComponent& - getPositionComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + template + [[nodiscard]] static inline auto getComponentCount(EntityManager& entities) { + auto query = entities.query().all(); + return query.count(); } - [[nodiscard]] inline const ecs::benchmarks::base::components::PlayerComponent& - getPlayerComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::PositionComponent& + getPositionComponent(EntityManager& entities, Entity entity) override { + return entities.set(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::HealthComponent& - getHealthComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponent(EntityManager& entities, Entity entity) override { + return entities.set(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::DamageComponent& - getDamageComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& + getHealthComponent(EntityManager& entities, Entity entity) override { + return entities.set(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::SpriteComponent& - getSpriteComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& + getDamageComponent(EntityManager& entities, Entity entity) override { + return entities.set(entity); } - ecs::benchmarks::base::components::PlayerType - initComponents(EntityManager& w, Entity e, - std::optional opt_player_type = std::nullopt) { - using namespace ecs::benchmarks::base::components; - - auto position = getPositionComponentConst(w, e); - auto player = getPlayerComponentConst(w, e); - auto health = getHealthComponentConst(w, e); - auto damage = getDamageComponentConst(w, e); - auto sprite = getSpriteComponentConst(w, e); - - auto ret = BaseHeroMonsterEntityFactory::setComponents(position, player, health, damage, sprite, opt_player_type); - - w.set(e) - .set(position) - .set(player) - .set(health) - .set(damage) - .set(sprite); + [[nodiscard]] inline ecs::benchmarks::base::components::SpriteComponent& + getSpriteComponent(EntityManager& entities, Entity entity) override { + return entities.set(entity); + } - return ret; + [[nodiscard]] inline const ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponentConst(EntityManager& entities, Entity entity) override { + return entities.get(entity); } }; diff --git a/src/gaia-ecs/gaia-ecs/entities/SoAEntityFactory.cpp b/src/gaia-ecs/gaia-ecs/entities/SoAEntityFactory.cpp index cebec93..503c09d 100644 --- a/src/gaia-ecs/gaia-ecs/entities/SoAEntityFactory.cpp +++ b/src/gaia-ecs/gaia-ecs/entities/SoAEntityFactory.cpp @@ -18,7 +18,7 @@ SoAEntityFactory::Entity SoAEntityFactory::createSingle(EntityManager& entities) SoAEntityFactory::Entity SoAEntityFactory::create(EntityManager& entities) { auto e = entities.add(); - entities.bulk(e) + entities.build(e) .add() .add() .add(); @@ -27,7 +27,7 @@ SoAEntityFactory::Entity SoAEntityFactory::create(EntityManager& entities) { SoAEntityFactory::Entity SoAEntityFactory::createMinimal(EntityManager& entities) { auto e = entities.add(); - entities.bulk(e).add().add(); + entities.build(e).add().add(); return e; } diff --git a/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.cpp b/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.cpp index 413fbe5..fc57e40 100644 --- a/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.cpp +++ b/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.cpp @@ -8,7 +8,7 @@ namespace ecs::benchmarks::gaia_ecs::entities { SoAHeroMonsterEntityFactory::Entity SoAHeroMonsterEntityFactory::createRandom(EntityManager& entities) { using namespace ecs::benchmarks::base::components; auto ret = entities.add(); - entities.bulk(ret) + entities.build(ret) .add() .add() .add() @@ -20,7 +20,7 @@ SoAHeroMonsterEntityFactory::Entity SoAHeroMonsterEntityFactory::createRandom(En SoAHeroMonsterEntityFactory::Entity SoAHeroMonsterEntityFactory::createHero(EntityManager& entities) { using namespace ecs::benchmarks::base::components; auto ret = entities.add(); - entities.bulk(ret) + entities.build(ret) .add() .add() .add() @@ -32,7 +32,7 @@ SoAHeroMonsterEntityFactory::Entity SoAHeroMonsterEntityFactory::createHero(Enti SoAHeroMonsterEntityFactory::Entity SoAHeroMonsterEntityFactory::createMonster(EntityManager& entities) { using namespace ecs::benchmarks::base::components; auto ret = entities.add(); - entities.bulk(ret) + entities.build(ret) .add() .add() .add() @@ -43,7 +43,7 @@ SoAHeroMonsterEntityFactory::Entity SoAHeroMonsterEntityFactory::createMonster(E } void SoAHeroMonsterEntityFactory::addComponents(EntityManager& entities, Entity entity) { - entities.bulk(entity) + entities.build(entity) .add() .add() .add() diff --git a/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.h b/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.h index ab69efa..ad70933 100644 --- a/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.h +++ b/src/gaia-ecs/gaia-ecs/entities/SoAHeroMonsterEntityFactory.h @@ -28,33 +28,40 @@ class SoAHeroMonsterEntityFactory { void addComponents(EntityManager& entities, Entity entity); - //[[nodiscard]] static inline auto getEntitiesCount(EntityManager& entities) { - // return entities.size(); - //} + template + [[nodiscard]] static inline auto getComponentCount(EntityManager& entities) { + auto query = entities.query().all(); + return query.count(); + } - [[nodiscard]] inline components::SoAPositionComponent getPositionComponentConst(EntityManager& entities, - Entity entity) { + [[nodiscard]] inline components::SoAPositionComponent + getPositionComponent(EntityManager& entities, Entity entity) { return entities.get(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::PlayerComponent& - getPlayerComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponent(EntityManager& entities, Entity entity) { + return entities.set(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::HealthComponent& - getHealthComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::HealthComponent& + getHealthComponent(EntityManager& entities, Entity entity) { + return entities.set(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::DamageComponent& - getDamageComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::DamageComponent& + getDamageComponent(EntityManager& entities, Entity entity) { + return entities.set(entity); } - [[nodiscard]] inline const ecs::benchmarks::base::components::SpriteComponent& - getSpriteComponentConst(EntityManager& entities, Entity entity) { - return entities.get(entity); + [[nodiscard]] inline ecs::benchmarks::base::components::SpriteComponent& + getSpriteComponent(EntityManager& entities, Entity entity) { + return entities.set(entity); + } + + [[nodiscard]] inline const ecs::benchmarks::base::components::PlayerComponent& + getPlayerComponentConst(EntityManager& entities, Entity entity) { + return entities.get(entity); } @@ -63,20 +70,15 @@ class SoAHeroMonsterEntityFactory { std::optional opt_player_type = std::nullopt) { using namespace ecs::benchmarks::base::components; - auto position = getPositionComponentConst(w, e); - auto player = getPlayerComponentConst(w, e); - auto health = getHealthComponentConst(w, e); - auto damage = getDamageComponentConst(w, e); - auto sprite = getSpriteComponentConst(w, e); + auto position = getPositionComponent(w, e); + auto& player = getPlayerComponent(w, e); + auto& health = getHealthComponent(w, e); + auto& damage = getDamageComponent(w, e); + auto& sprite = getSpriteComponent(w, e); auto ret = BaseHeroMonsterEntityFactory::setComponents(position, player, health, damage, sprite, opt_player_type); - w.set(e) - .set(position) - .set(player) - .set(health) - .set(damage) - .set(sprite); + w.set(e) = position; return ret; } diff --git a/src/gaia-ecs/gaia-ecs/systems/soa/SoAMoreComplexSystem.h b/src/gaia-ecs/gaia-ecs/systems/soa/SoAMoreComplexSystem.h index ec8d85b..3830500 100644 --- a/src/gaia-ecs/gaia-ecs/systems/soa/SoAMoreComplexSystem.h +++ b/src/gaia-ecs/gaia-ecs/systems/soa/SoAMoreComplexSystem.h @@ -26,7 +26,7 @@ class SoAMoreComplexSystem final : public ::gaia::ecs::System { void OnUpdate() override { // constexpr TimeDelta dt = 1.0F / 60.0F; - m_q.each([&](::gaia::ecs::Iter iter) { + m_q.each([&](::gaia::ecs::Iter& iter) { // Position auto vp = iter.view(); // read-only access to PositionSoA auto px = vp.get<0>(); // continuous block of "x" from PositionSoA diff --git a/src/gaia-ecs/gaia-ecs/systems/soa/SoAMovementSystem.h b/src/gaia-ecs/gaia-ecs/systems/soa/SoAMovementSystem.h index 55aaef4..a32f3f1 100644 --- a/src/gaia-ecs/gaia-ecs/systems/soa/SoAMovementSystem.h +++ b/src/gaia-ecs/gaia-ecs/systems/soa/SoAMovementSystem.h @@ -22,7 +22,7 @@ class SoAMovementSystem final : public ::gaia::ecs::System { void OnUpdate() override { constexpr TimeDelta dt = 1.0F / 60.0F; - m_q.each([&](::gaia::ecs::Iter iter) { + m_q.each([&](::gaia::ecs::Iter& iter) { // Position auto vp = iter.view_mut(); // read-write access to PositionSoA auto px = vp.set<0>(); // continuous block of "x" from PositionSoA diff --git a/src/gaia-ecs/gaia-ecs/systems/soa/SoARenderSystem.h b/src/gaia-ecs/gaia-ecs/systems/soa/SoARenderSystem.h index 0158cc6..68c4b5c 100644 --- a/src/gaia-ecs/gaia-ecs/systems/soa/SoARenderSystem.h +++ b/src/gaia-ecs/gaia-ecs/systems/soa/SoARenderSystem.h @@ -27,7 +27,7 @@ class SoARenderSystem final : public ::gaia::ecs::System { void OnUpdate() override { // constexpr TimeDelta dt = 1.0F / 60.0F; - m_q.each([&](::gaia::ecs::Iter iter) { + m_q.each([&](::gaia::ecs::Iter& iter) { // Position auto vp = iter.view(); // read-only access to PositionSoA auto px = vp.get<0>(); // continuous block of "x" from PositionSoA diff --git a/src/ginseng/ginseng/systems/RenderSystem.cpp b/src/ginseng/ginseng/systems/RenderSystem.cpp index 16a8f9c..bdfa57c 100644 --- a/src/ginseng/ginseng/systems/RenderSystem.cpp +++ b/src/ginseng/ginseng/systems/RenderSystem.cpp @@ -4,7 +4,7 @@ namespace ecs::benchmarks::ginseng::systems { -void RenderSystem::update(EntityManager& registry, TimeDelta dt) { +void RenderSystem::update(EntityManager& registry, TimeDelta /*dt*/) { registry.visit([&](const ecs::benchmarks::base::components::PositionComponent& position, const ecs::benchmarks::base::components::SpriteComponent& spr) { renderSprite(position, spr); diff --git a/src/oop/oop/OOPApplication.h b/src/oop/oop/OOPApplication.h index bf5846e..7a7bc28 100644 --- a/src/oop/oop/OOPApplication.h +++ b/src/oop/oop/OOPApplication.h @@ -9,7 +9,7 @@ namespace ecs::benchmarks::oop { class OOPApplication { public: using TimeDelta = float; - using EntityManager = entities::EntityManager; + using EntityManager = entities::OOPEntityManager; OOPApplication() : m_frameBuffer(320, 240) {} explicit OOPApplication(base::add_more_complex_system_t add_more_complex_system) diff --git a/src/oop/oop/entities/EntityFactory.h b/src/oop/oop/entities/EntityFactory.h index 3d5dbf2..cd74103 100644 --- a/src/oop/oop/entities/EntityFactory.h +++ b/src/oop/oop/entities/EntityFactory.h @@ -15,7 +15,7 @@ namespace ecs::benchmarks::oop::entities { -struct EntityManager { +struct OOPEntityManager { std::vector> game_objects; std::unordered_map> render_objects; }; @@ -23,7 +23,7 @@ struct EntityManager { class EntityFactory { public: using Entity = GameObject*; - using EntityManager = EntityManager; + using EntityManager = OOPEntityManager; base::add_more_complex_system_t add_more_complex_system{base::add_more_complex_system_t::UseBasicSystems}; diff --git a/src/openecs/CMakeLists.txt b/src/openecs/CMakeLists.txt index 384bb56..2f8621a 100755 --- a/src/openecs/CMakeLists.txt +++ b/src/openecs/CMakeLists.txt @@ -1,8 +1,16 @@ # add dependencies FIXME: Failed to unstash changes ... Encountered 2 file(s) that should have been pointers, but weren't: -# img/component_memory_pool.png img/componentmask_version_vector.png CPMAddPackage( NAME OpenECS VERSION 0.1.101 GITHUB_REPOSITORY -# Gronis/OpenEcs # TODO: set current version, use master (no release version) GIT_TAG master DOWNLOAD_ONLY True ) if(OpenECS_ADDED) -# add_library(OpenEcs INTERFACE) target_include_directories(OpenEcs SYSTEM INTERFACE ${OpenECS_SOURCE_DIR}/include) endif() workaround: use -# local files, see libs/ +# img/component_memory_pool.png img/componentmask_version_vector.png +## CPMAddPackage( NAME OpenECS +## VERSION 0.1.101 +## GITHUB_REPOSITORY +## Gronis/OpenEcs +## # TODO: set current version, use master (no release version) +## GIT_TAG master +## DOWNLOAD_ONLY True) +## if(OpenECS_ADDED) +## add_library(OpenEcs INTERFACE) target_include_directories(OpenEcs SYSTEM INTERFACE ${OpenECS_SOURCE_DIR}/include) +## endif() +# workaround: use local files, see libs/ set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "${CMAKE_PROJECT_NAME}-example-myecs" diff --git a/src/pico_ecs/CMakeLists.txt b/src/pico_ecs/CMakeLists.txt index 380d077..77f042e 100755 --- a/src/pico_ecs/CMakeLists.txt +++ b/src/pico_ecs/CMakeLists.txt @@ -1,3 +1,25 @@ +# https://github.com/empyreanx/pico_headers +CPMAddPackage( + NAME pico_headers + VERSION 2.3 + GITHUB_REPOSITORY empyreanx/pico_headers + # TODO: set current version, use master (no release version) + GIT_TAG main + DOWNLOAD_ONLY True +) +if(pico_headers_ADDED) + add_library(pico_headers INTERFACE) + target_include_directories(pico_headers SYSTEM INTERFACE ${pico_headers_SOURCE_DIR}) + + project(pico_ecs LANGUAGES C) + add_library(pico_ecs INTERFACE ${pico_headers_SOURCE_DIR}/pico_ecs.h) + add_library(pico_headers::pico_ecs ALIAS pico_ecs) + target_include_directories(pico_ecs INTERFACE "$") + + target_compile_definitions(pico_ecs INTERFACE $<$:NDEBUG>) +endif() + + set(INCLUDE_DIR "include") # must be relative paths # NOTE: rename project in "${CMAKE_PROJECT_NAME}-example-myecs" add_library( diff --git a/taskfiles/Benchmark.yml b/taskfiles/Benchmark.yml index 732a993..afcbeda 100644 --- a/taskfiles/Benchmark.yml +++ b/taskfiles/Benchmark.yml @@ -39,4 +39,9 @@ tasks: - task: flecs:complex - task: oop:complex - task: pico-ecs:complex - - task: gaia-ecs:complex \ No newline at end of file + - task: gaia-ecs:complex + + + events: + - task: entt:events + - task: flecs:events \ No newline at end of file diff --git a/taskfiles/Plot.yml b/taskfiles/Plot.yml index 8a756c2..821cd44 100644 --- a/taskfiles/Plot.yml +++ b/taskfiles/Plot.yml @@ -10,6 +10,7 @@ tasks: - task: default - task: entities - task: extended + - task: events default: - task: utils:gen-report-template @@ -40,6 +41,19 @@ tasks: # TODO: add openecs # {{.PROJECT_DIR}}/reports/openecs-entities.json + events: + - task: utils:gen-report-template + vars: + OUTPUT: events.RESULTS.md + REPORTS: > + {{.PROJECT_DIR}}/reports/entt-extended-event.json + {{.PROJECT_DIR}}/reports/entt-extended-event-comp.json + {{.PROJECT_DIR}}/reports/entt-extended-event-emit.json + {{.PROJECT_DIR}}/reports/entt-extended-event-emit-stable.json + # {{.PROJECT_DIR}}/reports/flecs-extended-event-emit.json + # {{.PROJECT_DIR}}/reports/flecs-extended-event.json + # {{.PROJECT_DIR}}/reports/mustache-extended-event.json + extended: - task: utils:gen-report-template vars: diff --git a/taskfiles/benchmarks/Entt.yml b/taskfiles/benchmarks/Entt.yml index 98493cb..546e8bd 100644 --- a/taskfiles/benchmarks/Entt.yml +++ b/taskfiles/benchmarks/Entt.yml @@ -10,6 +10,9 @@ tasks: - task: default - task: entities - task: extended + - task: extended-event + - task: extended-event-comp + - task: extended-event-emit - task: extended-runtime - task: extended-stable - task: extended-group @@ -17,6 +20,12 @@ tasks: - task: extended-full-owning-group - task: extended-partial-owning-group + events: + - task: extended-event + - task: extended-event-comp + - task: extended-event-emit + - task: extended-event-emit-stable + default: - task: utils:run-benchmark-template vars: @@ -110,4 +119,32 @@ tasks: REPORT_NAME: entt-complex-group BENCHMARK_ARGS: "--benchmark_filter=\"Complex\"" BENCHMARK_NAME: entt-extended-group + BENCHMARK_DIR: entt-extended + + extended-event: + - task: utils:run-benchmark-template + vars: + REPORT_NAME: entt-event + BENCHMARK_NAME: entt-extended-event + BENCHMARK_DIR: entt-extended + + extended-event-comp: + - task: utils:run-benchmark-template + vars: + REPORT_NAME: entt-event-comp + BENCHMARK_NAME: entt-extended-event-comp + BENCHMARK_DIR: entt-extended + + extended-event-emit: + - task: utils:run-benchmark-template + vars: + REPORT_NAME: entt-event-emit + BENCHMARK_NAME: entt-extended-event-emit + BENCHMARK_DIR: entt-extended + + extended-event-emit-stable: + - task: utils:run-benchmark-template + vars: + REPORT_NAME: entt-event-emit-stable + BENCHMARK_NAME: entt-extended-event-emit-stable BENCHMARK_DIR: entt-extended \ No newline at end of file diff --git a/taskfiles/benchmarks/Flecs.yml b/taskfiles/benchmarks/Flecs.yml index d72dd84..549ae39 100644 --- a/taskfiles/benchmarks/Flecs.yml +++ b/taskfiles/benchmarks/Flecs.yml @@ -10,6 +10,12 @@ tasks: - task: default - task: entities - task: extended + #- task: extended-event # @FIXME: AddressSanitizer:DEADLYSIGNAL + - task: extended-event-emit + + events: + #- task: extended-event # @FIXME: AddressSanitizer:DEADLYSIGNAL + - task: extended-event-emit default: - task: utils:run-benchmark-template @@ -38,4 +44,18 @@ tasks: REPORT_NAME: flecs-complex BENCHMARK_ARGS: "--benchmark_filter=\"Complex\"" BENCHMARK_NAME: flecs-extended - BENCHMARK_DIR: flecs-extended \ No newline at end of file + BENCHMARK_DIR: flecs-extended + + extended-event: + - task: utils:run-benchmark-template + vars: + BENCHMARK_NAME: flecs-extended-event + BENCHMARK_DIR: flecs-extended + REPORT_NAME: flecs-extended-event + + extended-event-emit: + - task: utils:run-benchmark-template + vars: + BENCHMARK_NAME: flecs-extended-event-emit + BENCHMARK_DIR: flecs-extended + REPORT_NAME: flecs-extended-event-emit \ No newline at end of file diff --git a/test/tests/CMakeLists.txt b/test/tests/CMakeLists.txt index c540c14..1ae8284 100755 --- a/test/tests/CMakeLists.txt +++ b/test/tests/CMakeLists.txt @@ -1,16 +1,12 @@ add_executable( ecs-benchmark-tests ${CMAKE_CURRENT_SOURCE_DIR}/entity_factory/entt_test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/entity_factory/flecs_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/entity_factory/entityx_test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/entity_factory/pico_ecs_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/entity_factory/gaia_ecs_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/application/entt_test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/application/flecs_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/application/entityx_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/application/ginseng_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/application/mustache_test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/application/pico_ecs_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/application/gaia_ecs_test.cpp) target_include_directories(ecs-benchmark-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(ecs-benchmark-tests PRIVATE ${PROJECT_SOURCE_DIR}/include) @@ -19,18 +15,46 @@ target_include_directories(ecs-benchmark-tests PRIVATE ${CMAKE_CURRENT_BINARY_DI target_link_libraries(ecs-benchmark-tests PRIVATE project_warnings project_options) target_compile_definitions(ecs-benchmark-tests PRIVATE TESTING) +# split into more tests ... error: duplicate symbol: _deps/flecs-build/libflecs_static.a(entity.c.o): src/pico_ecs/libecs-benchmark-example-pico-ecs.a(pico_ecs.cpp.o): ecs_new +add_executable( + ecs-benchmark-tests-flecs + ${CMAKE_CURRENT_SOURCE_DIR}/application/flecs_test.cpp) +target_include_directories(ecs-benchmark-tests-flecs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(ecs-benchmark-tests-flecs PRIVATE ${PROJECT_SOURCE_DIR}/include) +target_include_directories(ecs-benchmark-tests-flecs PRIVATE ${PROJECT_BINARY_DIR}/include) +target_include_directories(ecs-benchmark-tests-flecs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) +target_link_libraries(ecs-benchmark-tests-flecs PRIVATE project_warnings project_options) +target_compile_definitions(ecs-benchmark-tests-flecs PRIVATE TESTING) + +add_executable( + ecs-benchmark-tests-pico-ecs + ${CMAKE_CURRENT_SOURCE_DIR}/application/pico_ecs_test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/entity_factory/pico_ecs_test.cpp) +target_include_directories(ecs-benchmark-tests-pico-ecs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(ecs-benchmark-tests-pico-ecs PRIVATE ${PROJECT_SOURCE_DIR}/include) +target_include_directories(ecs-benchmark-tests-pico-ecs PRIVATE ${PROJECT_BINARY_DIR}/include) +target_include_directories(ecs-benchmark-tests-pico-ecs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) +target_link_libraries(ecs-benchmark-tests-pico-ecs PRIVATE project_warnings project_options) +target_compile_definitions(ecs-benchmark-tests-pico-ecs PRIVATE TESTING) + # @NOTE: add libs here target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark::base) target_link_system_libraries(ecs-benchmark-tests PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) +target_link_libraries(ecs-benchmark-tests-flecs PRIVATE ecs-benchmark::base) +target_link_system_libraries(ecs-benchmark-tests-flecs PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) +target_link_libraries(ecs-benchmark-tests-pico-ecs PRIVATE ecs-benchmark::base) +target_link_system_libraries(ecs-benchmark-tests-pico-ecs PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-entt) -target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-flecs) target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-entityx) target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-ginseng) target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-mustache) -target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-pico-ecs) target_link_libraries(ecs-benchmark-tests PRIVATE ecs-benchmark-example-gaia-ecs) +target_link_libraries(ecs-benchmark-tests-flecs PRIVATE ecs-benchmark-example-flecs) +target_link_libraries(ecs-benchmark-tests-pico-ecs PRIVATE ecs-benchmark-example-pico-ecs) # automatically discover tests that are defined in catch based test files you can modify the unittests. TEST_PREFIX to whatever you want, or # use different for different binaries catch_discover_tests(ecs-benchmark-tests) +catch_discover_tests(ecs-benchmark-tests-flecs) +catch_discover_tests(ecs-benchmark-tests-pico-ecs) diff --git a/test/tests/entity_factory/base.h b/test/tests/entity_factory/base.h index df82b0c..d829dfa 100644 --- a/test/tests/entity_factory/base.h +++ b/test/tests/entity_factory/base.h @@ -14,8 +14,8 @@ namespace ecs::benchmarks { template struct EntityFactory_Fixture { - using EntityManager = EntityFactory::EntityManager; - using Entity = EntityFactory::Entity; + using EntityManager = typename EntityFactory::EntityManager; + using Entity = typename EntityFactory::Entity; EntityFactory m_entity_factory;