Skip to content

Commit

Permalink
Merge branch 'release/4.7.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
abeimler committed Oct 1, 2023
2 parents f60acb8 + ea8027b commit 19a6e24
Show file tree
Hide file tree
Showing 60 changed files with 644 additions and 717 deletions.
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

44 changes: 11 additions & 33 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,13 @@ cpmaddpackage(
GITHUB_REPOSITORY
aminya/project_options
VERSION
0.30.0
0.32.1
# GIT_TAG main
DOWNLOAD_ONLY)
if(project_options_ADDED)
include(${project_options_SOURCE_DIR}/Index.cmake)
endif()

# Define the features of the project
include(CMakeDependentOption)
option(ENABLE_TESTING "Enable the tests" ${PROJECT_IS_TOP_LEVEL})
option(ENABLE_BENCHMARKS "Enable Benchmark" ON)
option(ENABLE_FUZZING "Enable Fuzzing Builds" OFF)
get_property(BUILDING_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(BUILDING_MULTI_CONFIG)
if(NOT CMAKE_BUILD_TYPE)
# Make sure that all supported configuration types have their associated conan packages available. You can reduce this list to only the
# configuration types you use, but only if one is not forced-set on the command line for VS
message(TRACE "Setting up multi-config build types")
set(CMAKE_CONFIGURATION_TYPES
Debug Release RelWithDebInfo MinSizeRel
CACHE STRING "Enabled build types" FORCE)
else()
message(TRACE "User chose a specific build type, so we are using that")
set(CMAKE_CONFIGURATION_TYPES
${CMAKE_BUILD_TYPE}
CACHE STRING "Enabled build types" FORCE)
endif()
endif()

option(ENABLE_CROSS_COMPILING "Detect cross compiler and setup toolchain" OFF)
if(ENABLE_CROSS_COMPILING)
enable_cross_compiler()
Expand All @@ -56,13 +34,14 @@ run_vcpkg()
# Set the project name and language
project(
ecs-benchmark
VERSION 4.7.3
VERSION 4.7.4
DESCRIPTION "Benchmarks of common ECS (Entity-Component-System)-Frameworks in C++ (or C)"
HOMEPAGE_URL "https://github.com/abeimler/ecs_benchmark"
LANGUAGES CXX C)
string(TOUPPER "${CMAKE_PROJECT_NAME}" CMAKE_PROJECT_NAME_UPPERCASE)
string(TOLOWER "${CMAKE_PROJECT_NAME}" CMAKE_PROJECT_NAME_LOWERCASE)
include(cmake/PreventInSourceBuilds.cmake)


# User options
include(cmake/CMakeOptions.cmake)
get_property(BUILDING_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
Expand All @@ -72,13 +51,13 @@ if(BUILDING_MULTI_CONFIG)
# configuration types you use, but only if one is not forced-set on the command line for VS
message(TRACE "Setting up multi-config build types")
set(CMAKE_CONFIGURATION_TYPES
Debug Release RelWithDebInfo MinSizeRel
CACHE STRING "Enabled build types" FORCE)
Debug Release RelWithDebInfo MinSizeRel
CACHE STRING "Enabled build types" FORCE)
else()
message(TRACE "User chose a specific build type, so we are using that")
set(CMAKE_CONFIGURATION_TYPES
${CMAKE_BUILD_TYPE}
CACHE STRING "Enabled build types" FORCE)
${CMAKE_BUILD_TYPE}
CACHE STRING "Enabled build types" FORCE)
endif()
endif()
include(cmake/ProjectOptions.cmake)
Expand Down Expand Up @@ -110,7 +89,6 @@ add_subdirectory(libs)
# add configure files
configure_file("${PROJECT_SOURCE_DIR}/include/Version.h.in" "${PROJECT_BINARY_DIR}/include/Version.h" @ONLY)


if(ENABLE_TESTING)
# This variable is set by project() in CMake 3.21+
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" PROJECT_IS_TOP_LEVEL)
Expand All @@ -125,7 +103,7 @@ endif()

if(ENABLE_FUZZING)
message(AUTHOR_WARNING "Building Fuzz Tests, using fuzzing sanitizer https://www.llvm.org/docs/LibFuzzer.html")
if (NOT OPT_ENABLE_ADDRESS_SANITIZER AND NOT OPT_ENABLE_THREAD_SANITIZER)
if(NOT OPT_ENABLE_ADDRESS_SANITIZER AND NOT OPT_ENABLE_THREAD_SANITIZER)
message(WARNING "You need asan or tsan enabled for meaningful fuzz testing")
endif()
add_subdirectory(fuzz_test)
Expand All @@ -138,8 +116,8 @@ endif()

add_subdirectory(src)

# If MSVC is being used, and ASAN is enabled, we need to set the debugger environment
# so that it behaves well with MSVC's debugger, and we can run the target from visual studio
# If MSVC is being used, and ASAN is enabled, we need to set the debugger environment so that it behaves well with MSVC's debugger, and we
# can run the target from visual studio
if(MSVC)
get_all_installable_targets(all_targets)
message("all_targets=${all_targets}")
Expand Down
367 changes: 187 additions & 180 deletions README.md

Large diffs are not rendered by default.

59 changes: 34 additions & 25 deletions README.md.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,51 @@
![License](https://img.shields.io/github/license/abeimler/ecs_benchmark)
![Standard](https://img.shields.io/badge/c%2B%2B-20-blue)

Simple Benchmarks of common ECS (Entity-Component-System) Frameworks:
This repository contains a collection of benchmarks for popular Entity-Component-System (ECS) frameworks. The benchmarks cover different aspects of ECS frameworks, such as update systems, component additions/removals, and entity creation/destruction.
Each benchmark is performed on three simple components and three small systems, which can be scaled to hundreds of components and systems in a real-world scenario. The results of the benchmarks are displayed in tables and charts, allowing you to compare the performance of different ECS frameworks in different areas.
It's important to note that different ECS frameworks have different strengths and weaknesses. For example, some frameworks might excel in adding/removing components, while others might be better at creating/destroying entities. Therefore, it's crucial to choose an ECS framework based on your specific requirements.

ECS (Entity-Component-System) Frameworks:

* [EntityX](https://github.com/alecthomas/entityx)
* [EnTT](https://github.com/skypjack/entt)
* [Ginseng](https://github.com/apples/ginseng)
* [mustache](https://github.com/kirillochnev/mustache)
* [flecs](https://github.com/SanderMertens/flecs)
* [pico_ecs](https://github.com/empyreanx/pico_headers)
* ~~TODO: [OpenEcs](https://github.com/Gronis/OpenEcs)~~

## TL;DR Results

The benchmark results are displayed in tables and charts,
allowing you to quickly compare the performance of different ECS frameworks in different scenarios. The tables include the time in nanoseconds it takes to perform the benchmark on different numbers of entities,
while the charts provide a visual representation of the results.
When using ECS frameworks, it's important to benchmark your specific use case and compare the results.
Therefore, the results of these benchmarks should be used as a starting point for your own benchmarking efforts.

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

{{{ComplexSystemsUpdateMixedEntities}}}


This is a very little Benchmark with three simple components and three small systems. In wild Entity-Component-Systems can have hundreds of components and a lot of systems and even more complex systems.
So always benchmarks YOUR special cases and systems, when needed and compare.
While this benchmark only includes three simple components and three small systems,
it's important to note that Entity-Component-Systems can become much more complex in the wild,
with hundreds of components and systems.
Therefore, it's crucial to always benchmark your specific cases and systems when necessary and compare results.
Different ECS frameworks excel in different areas, such as faster adding/removing of components or creating/destroying entities.
Therefore, it's essential to choose an ECS framework based on its features.
For example, EnTT offers [resource management](https://github.com/skypjack/entt/wiki/Crash-Course:-resource-management) and [event handling](https://github.com/skypjack/entt/wiki/Crash-Course:-events,-signals-and-everything-in-between), while flecs provides useful [add-ons](https://github.com/SanderMertens/flecs#addons), and EntityX includes a built-in [world/system manager](https://github.com/alecthomas/entityx#manager-tying-it-all-together=).

Some frameworks are faster in adding/removing components, others in creating or destroying entities, it always depends on what you need the most.
Always choose an ECS-Framework by features, for example EnTT has some great features like a
[resource-management](https://github.com/skypjack/entt/wiki/Crash-Course:-resource-management) or [events](https://github.com/skypjack/entt/wiki/Crash-Course:-events,-signals-and-everything-in-between),
flecs has some nice [add-ons](https://github.com/SanderMertens/flecs#addons) and EntityX has a build-in [world/system-manager](https://github.com/alecthomas/entityx#manager-tying-it-all-together=).

Pick and evaluate a framework you like and have a look at the examples and API design.
To evaluate a framework, look at its examples and API design, and pick the one that suits your needs the best.


## Details

### Features

All benchmarks are located in [`benchmark/benchmarks/`](benchmark/benchmarks/) and are written with [google/benchmark](https://github.com/google/benchmark).
Each benchmark must implement the template [ECSBenchmark.h](benchmark/benchmarks/ECSBenchmark.h).
All benchmarks are located in the [`benchmark/benchmarks/`](benchmark/benchmarks/) directory and are implemented with the [google/benchmark](https://github.com/google/benchmark) library.
Each benchmark must implement the `ECSBenchmark.h` template.

Each framework has a sub-project in [`src/`](src) and must implement certain features (see [`src/base`](src/base)).
Each framework has its own sub-project in the [`src/`](src) directory and must implement specific features (see [`src/base`](src/base)).

#### Components

Expand All @@ -54,18 +63,17 @@ Each framework has a sub-project in [`src/`](src) and must implement certain fea
3. `MoreComplexSystem`: updates Components with random data and nonsense


## Additional Benchmarks

## More Benchmarks

Benchmarks of more common features, like "Creating entities", "Add and remove components", etc.
Benchmarks for more common features, such as "Creating entities", "Adding and removing components", and others.

### Features tested

* Create Entities
* Destroy Entities
* Get Component(s)
* Remove and add component
* Systems (for-each entities)
* Entity Creation
* Entity Destruction
* Component Retrieval
* Adding and Removing Components
* Systems (for iterating through entities)


{{#environment}}
Expand Down Expand Up @@ -197,11 +205,12 @@ Benchmarks of more common features, like "Creating entities", "Add and remove co

## Contributing

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

You can find the frameworks example(s) in [`src/`](src/) and benchmark [`benchmarks/`](benchmarks/benchmarks/) for more details.
Also, you can write tests for the framework example :)
and add some metadata in [plot.config.json](plot.config.json).
Additionally, you can write tests for the framework example and add some metadata to the [plot.config.json](plot.config.json) file.
Any contributions are greatly appreciated!

_TODO: make more detailed "how to add framework"_

Expand Down
8 changes: 4 additions & 4 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ tasks:
vars:
FEATURE_TESTS: OFF
CMAKE_BUILD_TYPE: Release
CONFIGURE_FLAGS: -DDISABLE_SANITIZER:BOOL=ON
CONFIGURE_FLAGS: -DOPT_ENABLE_SANITIZER_ADDRESS:BOOL=OFF -DOPT_ENABLE_SANITIZER_UNDEFINED:BOOL=OFF -DOPT_ENABLE_COVERAGE:BOOL=OFF
- task: build-template
vars:
CMAKE_BUILD_TYPE: Release
Expand Down Expand Up @@ -111,7 +111,7 @@ tasks:
vars:
FEATURE_TESTS: ON
CMAKE_BUILD_TYPE: Debug
CONFIGURE_FLAGS: -DDISABLE_SANITIZER:BOOL=ON
CONFIGURE_FLAGS: -DOPT_ENABLE_SANITIZER_ADDRESS:BOOL=OFF -DOPT_ENABLE_SANITIZER_UNDEFINED:BOOL=OFF
- task: build-template
vars:
CMAKE_BUILD_TYPE: Debug
Expand All @@ -124,7 +124,7 @@ tasks:
vars:
FEATURE_TESTS: ON
CMAKE_BUILD_TYPE: RelWithDebInfo
CONFIGURE_FLAGS: -DDISABLE_SANITIZER:BOOL=ON
CONFIGURE_FLAGS: -DOPT_ENABLE_SANITIZER_ADDRESS:BOOL=OFF -DOPT_ENABLE_SANITIZER_UNDEFINED:BOOL=OFF
- task: build-template
vars:
CMAKE_BUILD_TYPE: RelWithDebInfo
Expand All @@ -137,7 +137,7 @@ tasks:
vars:
FEATURE_TESTS: ON
CMAKE_BUILD_TYPE: Release
CONFIGURE_FLAGS: -DDISABLE_SANITIZER:BOOL=ON
CONFIGURE_FLAGS: -DOPT_ENABLE_SANITIZER_ADDRESS:BOOL=OFF -DOPT_ENABLE_SANITIZER_UNDEFINED:BOOL=OFF
- task: build-template
vars:
CMAKE_BUILD_TYPE: Release
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.7.3
4.7.4
28 changes: 15 additions & 13 deletions benchmark/benchmarks/BaseECSBenchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ concept HasAddComponentsFeatures = requires(EntityFactory entity_factory, Entity
};
template <class EntityFactory, class EntityManager = typename EntityFactory::EntityManager,
class Entity = typename EntityFactory::Entity>
concept HasRemoveComponentsFeatures = requires(EntityFactory entity_factory, EntityManager entity_manager,
Entity entity) {
entity_factory.removeComponentOne(entity_manager, entity);
entity_factory.removeComponentTwo(entity_manager, entity);
entity_factory.removeComponentThree(entity_manager, entity);
};
concept HasRemoveComponentsFeatures =
requires(EntityFactory entity_factory, EntityManager entity_manager, Entity entity) {
entity_factory.removeComponentOne(entity_manager, entity);
entity_factory.removeComponentTwo(entity_manager, entity);
entity_factory.removeComponentThree(entity_manager, entity);
};
template <class EntityFactory, class EntityManager = typename EntityFactory::EntityManager,
class Entity = typename EntityFactory::Entity>
concept HasComponentsFeatures = HasAddComponentsFeatures<EntityFactory, EntityManager, Entity> &&
HasRemoveComponentsFeatures<EntityFactory, EntityManager, Entity>;
HasRemoveComponentsFeatures<EntityFactory, EntityManager, Entity>;


template <class EntityFactory>
Expand Down Expand Up @@ -128,8 +128,9 @@ class BaseECSBenchmark {

template <class tEntityFactory, class tEntityManager = typename tEntityFactory::EntityManager,
bool destory_entites = false>
requires HasRemoveComponentsFeatures<tEntityFactory> ComponentsCounter
createEntitiesWithMixedComponents(tEntityManager& registry, size_t nentities, std::vector<Entity>& out) {
requires HasRemoveComponentsFeatures<tEntityFactory>
ComponentsCounter createEntitiesWithMixedComponents(tEntityManager& registry, size_t nentities,
std::vector<Entity>& out) {
ComponentsCounter components_counter;
out.clear();
out.reserve(nentities);
Expand Down Expand Up @@ -169,7 +170,7 @@ class BaseECSBenchmark {
return components_counter;
}
template <class tEntityFactory, class tEntityManager = typename tEntityFactory::EntityManager>
requires HasRemoveComponentsFeatures<tEntityFactory>
requires HasRemoveComponentsFeatures<tEntityFactory>
inline ComponentsCounter createEntitiesWithMixedComponentsAndDestroyedEntitites(tEntityManager& registry,
size_t nentities,
std::vector<Entity>& out) {
Expand All @@ -178,8 +179,9 @@ class BaseECSBenchmark {

template <class tEntityFactory, class tEntityManager = typename tEntityFactory::EntityManager,
bool destory_entites = false>
requires HasAddComponentsFeatures<tEntityFactory> ComponentsCounter
createEntitiesWithMixedComponentsFromEmpty(tEntityManager& registry, size_t nentities, std::vector<Entity>& out) {
requires HasAddComponentsFeatures<tEntityFactory>
ComponentsCounter createEntitiesWithMixedComponentsFromEmpty(tEntityManager& registry, size_t nentities,
std::vector<Entity>& out) {
ComponentsCounter components_counter;
out.clear();
out.reserve(nentities);
Expand Down Expand Up @@ -232,7 +234,7 @@ class BaseECSBenchmark {
return components_counter;
}
template <class tEntityFactory = EntityFactory, class tEntityManager = typename tEntityFactory::EntityManager>
requires HasAddComponentsFeatures<tEntityFactory>
requires HasAddComponentsFeatures<tEntityFactory>
inline ComponentsCounter createEntitiesWithMixedComponentsAndDestroyedEntitiesFromEmpty(tEntityManager& registry,
size_t nentities,
std::vector<Entity>& out) {
Expand Down
Loading

0 comments on commit 19a6e24

Please sign in to comment.