performance improvement
This commit is contained in:
19
README.md
19
README.md
@@ -1068,7 +1068,7 @@ All of them have pros and cons to take in consideration. In particular:
|
||||
|
||||
* Once prepared, creating and destroying them isn't expensive at all because
|
||||
they don't have any type of initialization.
|
||||
* They are the best tool for iterating entities for mmultiple components and
|
||||
* They are the best tool for iterating entities for multiple components when
|
||||
most entities have them all.
|
||||
|
||||
Cons:
|
||||
@@ -1100,12 +1100,21 @@ All of them have pros and cons to take in consideration. In particular:
|
||||
To sum up and as a rule of thumb:
|
||||
|
||||
* Use a raw view to iterate components only (no entities) for a given type.
|
||||
* Use a standard view to iterate entities for a single component.
|
||||
* Use a standard view to iterate entities for multiple components when a
|
||||
significantly low number of entities have one of the components.
|
||||
* Use a standard view to iterate entities and components for a single type.
|
||||
* Use a standard view to iterate entities and components for multiple types when
|
||||
the number of types is low. Standard views are really optimized and persistent
|
||||
views won't add much in this case.
|
||||
* Use a standard view to iterate entities and components for multiple types when
|
||||
a significantly low number of entities have one of the components.
|
||||
* Use a standard view in all those cases where a persistent view would give a
|
||||
boost to performance but the iteration isn't performed frequently.
|
||||
* Prepare and use a persistent view in all the other cases.
|
||||
* Prepare and use a persistent view when you want to iterate only entities for
|
||||
multiple components.
|
||||
* Prepare and use a persistent view when you want to iterate entities for
|
||||
multiple components and each component is assigned to a great number of
|
||||
entities but the intersection between the sets of entities is small.
|
||||
* Prepare and use a persistent view in all the cases where a standard view
|
||||
wouldn't fit well otherwise.
|
||||
|
||||
To easily iterate entities and components, all the views offer the common
|
||||
`begin` and `end` member functions that allow users to use a view in a typical
|
||||
|
||||
3
TODO
3
TODO
@@ -5,7 +5,8 @@
|
||||
* define basic reactive systems (track entities to which component is attached, track entities from which component is removed, and so on)
|
||||
* define systems as composable mixins (initializazion, reactive, update, whatever) with flexible auto-detected arguments (registry, views, etc)
|
||||
* does it worth it to add an optional functor to the member functions of snapshot so as to filter out instances and entities?
|
||||
* allow for custom sort functions on registry/view sort (unlikely std::sort is the best function ever in game programming)
|
||||
* ease the assignment of tags as string (use a template class with a non-type template parameter behind the scene)
|
||||
* dictionary based dependency class (templates copied over) + prefabs (shared state/copy-on-write)
|
||||
* prototype entities, a really interesting feature (see #56)
|
||||
* "singleton mode" for tags (see #66)
|
||||
* AOB
|
||||
|
||||
@@ -143,7 +143,7 @@ struct Actor {
|
||||
* @return A reference to the instance of the tag owned by the actor.
|
||||
*/
|
||||
template<typename Tag>
|
||||
Tag & get(tag_t) ENTT_NOEXCEPT {
|
||||
inline Tag & get(tag_t) ENTT_NOEXCEPT {
|
||||
return const_cast<Tag &>(const_cast<const Actor *>(this)->get<Tag>(tag_t{}));
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ struct Actor {
|
||||
* @return A reference to the instance of the component owned by the actor.
|
||||
*/
|
||||
template<typename Component>
|
||||
Component & get() ENTT_NOEXCEPT {
|
||||
inline Component & get() ENTT_NOEXCEPT {
|
||||
return const_cast<Component &>(const_cast<const Actor *>(this)->get<Component>());
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ struct Actor {
|
||||
* @brief Returns a reference to the underlying registry.
|
||||
* @return A reference to the underlying registry.
|
||||
*/
|
||||
registry_type & registry() ENTT_NOEXCEPT {
|
||||
inline registry_type & registry() ENTT_NOEXCEPT {
|
||||
return const_cast<registry_type &>(const_cast<const Actor *>(this)->registry());
|
||||
}
|
||||
|
||||
|
||||
@@ -44,14 +44,15 @@ class Registry {
|
||||
|
||||
template<typename... Component>
|
||||
static void creating(Registry ®istry, Entity entity) {
|
||||
const auto ttype = handler_family::type<Component...>();
|
||||
return registry.has<Component...>(entity) ? registry.handlers[ttype]->construct(entity) : void();
|
||||
if(registry.has<Component...>(entity)) {
|
||||
registry.handlers[handler_family::type<Component...>()]->construct(entity);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Component>
|
||||
static void destroying(Registry ®istry, Entity entity) {
|
||||
auto &handler = registry.handlers[handler_family::type<Component...>()];
|
||||
return handler->has(entity) ? handler->destroy(entity) : void();
|
||||
auto &handler = *registry.handlers[handler_family::type<Component...>()];
|
||||
return handler.has(entity) ? handler.destroy(entity) : void();
|
||||
}
|
||||
|
||||
struct Attachee {
|
||||
@@ -85,7 +86,7 @@ class Registry {
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
SparseSet<Entity, Component> & pool() ENTT_NOEXCEPT {
|
||||
inline SparseSet<Entity, Component> & pool() ENTT_NOEXCEPT {
|
||||
return const_cast<SparseSet<Entity, Component> &>(const_cast<const Registry *>(this)->pool<Component>());
|
||||
}
|
||||
|
||||
@@ -153,7 +154,7 @@ public:
|
||||
* @return Runtime numeric identifier of the given type of tag.
|
||||
*/
|
||||
template<typename Tag>
|
||||
tag_type type(tag_t) const ENTT_NOEXCEPT {
|
||||
static tag_type type(tag_t) ENTT_NOEXCEPT {
|
||||
return tag_family::type<Tag>();
|
||||
}
|
||||
|
||||
@@ -170,7 +171,7 @@ public:
|
||||
* @return Runtime numeric identifier of the given type of component.
|
||||
*/
|
||||
template<typename Component>
|
||||
component_type type() const ENTT_NOEXCEPT {
|
||||
static component_type type() ENTT_NOEXCEPT {
|
||||
return component_family::type<Component>();
|
||||
}
|
||||
|
||||
@@ -280,7 +281,7 @@ public:
|
||||
* @return A pointer to the array of components of the given type.
|
||||
*/
|
||||
template<typename Component>
|
||||
Component * raw() ENTT_NOEXCEPT {
|
||||
inline Component * raw() ENTT_NOEXCEPT {
|
||||
return const_cast<Component *>(const_cast<const Registry *>(this)->raw<Component>());
|
||||
}
|
||||
|
||||
@@ -619,7 +620,7 @@ public:
|
||||
* @return A reference to the tag.
|
||||
*/
|
||||
template<typename Tag>
|
||||
Tag & get() ENTT_NOEXCEPT {
|
||||
inline Tag & get() ENTT_NOEXCEPT {
|
||||
return const_cast<Tag &>(const_cast<const Registry *>(this)->get<Tag>());
|
||||
}
|
||||
|
||||
@@ -659,7 +660,7 @@ public:
|
||||
* @return A reference to the component owned by the entity.
|
||||
*/
|
||||
template<typename Component>
|
||||
Component & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
inline Component & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
return const_cast<Component &>(const_cast<const Registry *>(this)->get<Component>(entity));
|
||||
}
|
||||
|
||||
|
||||
@@ -470,7 +470,7 @@ class ContinuousLoader final {
|
||||
|
||||
each(archive, [&archive, member..., this](auto entity) {
|
||||
entity = restore(entity);
|
||||
auto &tag = registry.template assign<Tag>(entt::tag_t{}, entity);
|
||||
auto &tag = registry.template assign<Tag>(tag_t{}, entity);
|
||||
archive(tag);
|
||||
|
||||
using accumulator_type = int[];
|
||||
|
||||
@@ -692,7 +692,7 @@ public:
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The object associated to the entity.
|
||||
*/
|
||||
object_type & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
inline object_type & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
return const_cast<object_type &>(const_cast<const SparseSet *>(this)->get(entity));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,39 +5,19 @@
|
||||
namespace entt {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Tag class type.
|
||||
*
|
||||
* An empty class type used to disambiguate the overloads of some member
|
||||
* functions.
|
||||
*/
|
||||
/*! @brief Tag class type used to disambiguate overloads. */
|
||||
struct tag_t final {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Persistent view type.
|
||||
*
|
||||
* An empty class type used to disambiguate the overloads of some member
|
||||
* functions.
|
||||
*/
|
||||
/*! @brief Persistent view type used to disambiguate overloads. */
|
||||
struct persistent_t final {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Raw view type.
|
||||
*
|
||||
* An empty class type used to disambiguate the overloads of some member
|
||||
* functions.
|
||||
*/
|
||||
/*! @brief Raw view type used to disambiguate overloads. */
|
||||
struct raw_t final {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Break type.
|
||||
*
|
||||
* An empty class type used to disambiguate the overloads of some member
|
||||
* functions.
|
||||
*/
|
||||
/*! @brief Break type used to disambiguate overloads. */
|
||||
struct break_t final {};
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include "../config/config.h"
|
||||
#include "../core/ident.hpp"
|
||||
#include "entt_traits.hpp"
|
||||
#include "sparse_set.hpp"
|
||||
|
||||
@@ -247,7 +248,7 @@ public:
|
||||
* @return The component assigned to the entity.
|
||||
*/
|
||||
template<typename Comp>
|
||||
Comp & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
inline Comp & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
return const_cast<Comp &>(const_cast<const PersistentView *>(this)->get<Comp>(entity));
|
||||
}
|
||||
|
||||
@@ -339,9 +340,9 @@ public:
|
||||
* @param func A valid function object.
|
||||
*/
|
||||
template<typename Func>
|
||||
void each(Func func) {
|
||||
std::for_each(view.begin(), view.end(), [&func, this](const auto entity) {
|
||||
func(entity, std::get<pool_type<Component> &>(pools).get(entity)...);
|
||||
inline void each(Func func) {
|
||||
const_cast<const PersistentView *>(this)->each([&func](entity_type entity, const Component &... component) {
|
||||
func(entity, const_cast<Component &>(component)...);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -428,6 +429,28 @@ class View final {
|
||||
using pattern_type = std::tuple<pool_type<Component> &...>;
|
||||
using traits_type = entt_traits<Entity>;
|
||||
|
||||
template<typename...>
|
||||
struct ComponentList {};
|
||||
|
||||
template<typename, typename, typename = ComponentList<>, typename = void>
|
||||
struct SplitComponentListBy;
|
||||
|
||||
template<typename Comp, typename Next, typename... Other, typename... Types>
|
||||
struct SplitComponentListBy<Comp, ComponentList<Next, Other...>, ComponentList<Types...>, std::enable_if_t<std::is_same<Comp, Next>::value>> {
|
||||
using pre_type = ComponentList<Types...>;
|
||||
using post_type = ComponentList<Other...>;
|
||||
};
|
||||
|
||||
template<typename Comp, typename Next, typename... Other, typename... Types>
|
||||
struct SplitComponentListBy<Comp, ComponentList<Next, Other...>, ComponentList<Types...>, std::enable_if_t<!std::is_same<Comp, Next>::value>>
|
||||
: SplitComponentListBy<Comp, ComponentList<Other...>, ComponentList<Types..., Next>> {};
|
||||
|
||||
template<typename Comp>
|
||||
using PreList = typename SplitComponentListBy<Comp, ComponentList<Component...>>::pre_type;
|
||||
|
||||
template<typename Comp>
|
||||
using PostList = typename SplitComponentListBy<Comp, ComponentList<Component...>>::post_type;
|
||||
|
||||
class Iterator {
|
||||
using size_type = typename view_type::size_type;
|
||||
|
||||
@@ -498,11 +521,32 @@ class View final {
|
||||
};
|
||||
|
||||
View(pool_type<Component> &... pools) ENTT_NOEXCEPT
|
||||
: pools{pools...}, view{nullptr}, unchecked{}
|
||||
: pools{pools...}, view{nullptr}, unchecked{}, idx{}
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
template<typename Comp, typename... Pre, typename... Post, typename Func>
|
||||
void each(Func func, ComponentList<Pre...>, ComponentList<Post...>) const {
|
||||
const auto extent = std::min({ std::get<pool_type<Component> &>(pools).extent()... });
|
||||
auto &pool = std::get<pool_type<Comp> &>(pools);
|
||||
|
||||
std::for_each(pool.view_type::cbegin(), pool.view_type::cend(), [&func, raw = pool.cbegin(), extent, this](const auto entity) mutable {
|
||||
const auto sz = size_type(entity & traits_type::entity_mask);
|
||||
|
||||
if(sz < extent) {
|
||||
auto pos = unchecked.size();
|
||||
|
||||
for(; pos && unchecked[pos-1]->fast(entity); --pos);
|
||||
|
||||
if(!pos) {
|
||||
// avoided indirections due to the sparse set for the pivot
|
||||
func(entity, std::get<pool_type<Pre> &>(pools).get(entity)..., *(raw)++, std::get<pool_type<Post> &>(pools).get(entity)...);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Input iterator type. */
|
||||
using iterator_type = Iterator;
|
||||
@@ -663,7 +707,7 @@ public:
|
||||
* @return The component assigned to the entity.
|
||||
*/
|
||||
template<typename Comp>
|
||||
Comp & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
inline Comp & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
return const_cast<Comp &>(const_cast<const View *>(this)->get<Comp>(entity));
|
||||
}
|
||||
|
||||
@@ -732,22 +776,11 @@ public:
|
||||
* @param func A valid function object.
|
||||
*/
|
||||
template<typename Func>
|
||||
void each(Func func) const {
|
||||
const auto extent = std::min({ std::get<pool_type<Component> &>(pools).extent()... });
|
||||
|
||||
std::for_each(view->cbegin(), view->cend(), [&func, extent, this](const auto entity) {
|
||||
const auto sz = size_type(entity & traits_type::entity_mask);
|
||||
|
||||
if(sz < extent) {
|
||||
auto pos = unchecked.size();
|
||||
|
||||
for(; pos && unchecked[pos-1]->fast(entity); --pos);
|
||||
|
||||
if(!pos) {
|
||||
func(entity, std::get<pool_type<Component> &>(pools).get(entity)...);
|
||||
}
|
||||
}
|
||||
});
|
||||
inline void each(Func func) const {
|
||||
constexpr auto indexes = ident<Component...>;
|
||||
using accumulator_type = int[];
|
||||
accumulator_type accumulator = { (indexes.template get<Component>() == idx ? (each<Component>(std::move(func), PreList<Component>{}, PostList<Component>{}), 0) : 0)... };
|
||||
(void)accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -767,7 +800,7 @@ public:
|
||||
* @param func A valid function object.
|
||||
*/
|
||||
template<typename Func>
|
||||
void each(Func func) {
|
||||
inline void each(Func func) {
|
||||
const_cast<const View *>(this)->each([&func](entity_type entity, const Component &... component) {
|
||||
func(entity, const_cast<Component &>(component)...);
|
||||
});
|
||||
@@ -786,18 +819,18 @@ public:
|
||||
void reset() {
|
||||
using accumulator_type = size_type[];
|
||||
size_type sz = std::max({ std::get<pool_type<Component> &>(pools).size()... }) + std::size_t{1};
|
||||
size_type pos{};
|
||||
size_type next{};
|
||||
|
||||
auto probe = [this](auto sz, const auto &pool) {
|
||||
return pool.size() < sz ? (view = &pool, pool.size()) : sz;
|
||||
};
|
||||
|
||||
auto filter = [this](auto pos, const auto &pool) {
|
||||
return (view != &pool) ? (unchecked[pos++] = &pool, pos) : pos;
|
||||
auto filter = [this](auto next, const auto &pool) {
|
||||
return (view == &pool) ? (idx = next) : (unchecked[next++] = &pool, next);
|
||||
};
|
||||
|
||||
accumulator_type probing = { (sz = probe(sz, std::get<pool_type<Component> &>(pools)))... };
|
||||
accumulator_type filtering = { (pos = filter(pos, std::get<pool_type<Component> &>(pools)))... };
|
||||
accumulator_type filtering = { (next = filter(next, std::get<pool_type<Component> &>(pools)))... };
|
||||
|
||||
(void)filtering;
|
||||
(void)probing;
|
||||
@@ -807,6 +840,7 @@ private:
|
||||
const pattern_type pools;
|
||||
const view_type *view;
|
||||
unchecked_type unchecked;
|
||||
size_type idx;
|
||||
};
|
||||
|
||||
|
||||
@@ -915,7 +949,7 @@ public:
|
||||
*
|
||||
* @return A pointer to the array of components.
|
||||
*/
|
||||
raw_type * raw() ENTT_NOEXCEPT {
|
||||
inline raw_type * raw() ENTT_NOEXCEPT {
|
||||
return const_cast<raw_type *>(const_cast<const View *>(this)->raw());
|
||||
}
|
||||
|
||||
@@ -1053,7 +1087,7 @@ public:
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The component assigned to the entity.
|
||||
*/
|
||||
Component & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
inline Component & get(entity_type entity) ENTT_NOEXCEPT {
|
||||
return const_cast<Component &>(const_cast<const View *>(this)->get(entity));
|
||||
}
|
||||
|
||||
@@ -1074,8 +1108,8 @@ public:
|
||||
*/
|
||||
template<typename Func>
|
||||
void each(Func func) const {
|
||||
std::for_each(pool.view_type::cbegin(), pool.view_type::cend(), [&func, this](const auto entity) {
|
||||
func(entity, pool.get(entity));
|
||||
std::for_each(pool.view_type::cbegin(), pool.view_type::cend(), [&func, raw = pool.cbegin()](const auto entity) mutable {
|
||||
func(entity, *(raw++));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1095,9 +1129,9 @@ public:
|
||||
* @param func A valid function object.
|
||||
*/
|
||||
template<typename Func>
|
||||
void each(Func func) {
|
||||
std::for_each(pool.view_type::begin(), pool.view_type::end(), [&func, this](const auto entity) {
|
||||
func(entity, pool.get(entity));
|
||||
inline void each(Func func) {
|
||||
const_cast<const View *>(this)->each([&func](entity_type entity, const Component &component) {
|
||||
func(entity, const_cast<Component &>(component));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1211,7 +1245,7 @@ public:
|
||||
*
|
||||
* @return A pointer to the array of components.
|
||||
*/
|
||||
raw_type * raw() ENTT_NOEXCEPT {
|
||||
inline raw_type * raw() ENTT_NOEXCEPT {
|
||||
return const_cast<raw_type *>(const_cast<const RawView *>(this)->raw());
|
||||
}
|
||||
|
||||
|
||||
@@ -77,13 +77,11 @@ TEST(Benchmark, IterateCreateDeleteSingleComponent) {
|
||||
registry.assign<Position>(entity);
|
||||
}
|
||||
|
||||
view.each([&](auto entity, auto &position) {
|
||||
(void)position;
|
||||
|
||||
for(auto entity: view) {
|
||||
if(rand() % 2 == 0) {
|
||||
registry.destroy(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
timer.elapsed();
|
||||
@@ -99,9 +97,16 @@ TEST(Benchmark, IterateSingleComponent1M) {
|
||||
registry.assign<Position>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position>().each([](auto, auto &) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &) {});
|
||||
test([](auto, auto &position) {
|
||||
position.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateSingleComponentRaw1M) {
|
||||
@@ -114,11 +119,16 @@ TEST(Benchmark, IterateSingleComponentRaw1M) {
|
||||
registry.assign<Position>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
for(auto &&component: registry.view<Position>(entt::raw_t{})) {
|
||||
(void)component;
|
||||
}
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position>(entt::raw_t{}).each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](const auto &) {});
|
||||
test([](auto &position) {
|
||||
position.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTwoComponents1M) {
|
||||
@@ -132,9 +142,17 @@ TEST(Benchmark, IterateTwoComponents1M) {
|
||||
registry.assign<Velocity>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTwoComponents1MHalf) {
|
||||
@@ -151,9 +169,17 @@ TEST(Benchmark, IterateTwoComponents1MHalf) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTwoComponents1MOne) {
|
||||
@@ -170,9 +196,17 @@ TEST(Benchmark, IterateTwoComponents1MOne) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTwoComponentsPersistent1M) {
|
||||
@@ -187,9 +221,17 @@ TEST(Benchmark, IterateTwoComponentsPersistent1M) {
|
||||
registry.assign<Velocity>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>(entt::persistent_t{}).each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity>(entt::persistent_t{}).each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateFiveComponents1M) {
|
||||
@@ -206,9 +248,20 @@ TEST(Benchmark, IterateFiveComponents1M) {
|
||||
registry.assign<Comp<3>>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateFiveComponents1MHalf) {
|
||||
@@ -228,9 +281,20 @@ TEST(Benchmark, IterateFiveComponents1MHalf) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateFiveComponents1MOne) {
|
||||
@@ -250,9 +314,20 @@ TEST(Benchmark, IterateFiveComponents1MOne) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateFiveComponentsPersistent1M) {
|
||||
@@ -270,9 +345,20 @@ TEST(Benchmark, IterateFiveComponentsPersistent1M) {
|
||||
registry.assign<Comp<3>>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>(entt::persistent_t{}).each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>(entt::persistent_t{}).each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTenComponents1M) {
|
||||
@@ -294,9 +380,25 @@ TEST(Benchmark, IterateTenComponents1M) {
|
||||
registry.assign<Comp<8>>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3, auto &comp4, auto &comp5, auto &comp6, auto &comp7, auto &comp8) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
comp4.x = {};
|
||||
comp5.x = {};
|
||||
comp6.x = {};
|
||||
comp7.x = {};
|
||||
comp8.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTenComponents1MHalf) {
|
||||
@@ -321,9 +423,25 @@ TEST(Benchmark, IterateTenComponents1MHalf) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3, auto &comp4, auto &comp5, auto &comp6, auto &comp7, auto &comp8) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
comp4.x = {};
|
||||
comp5.x = {};
|
||||
comp6.x = {};
|
||||
comp7.x = {};
|
||||
comp8.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTenComponents1MOne) {
|
||||
@@ -348,9 +466,25 @@ TEST(Benchmark, IterateTenComponents1MOne) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>().each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3, auto &comp4, auto &comp5, auto &comp6, auto &comp7, auto &comp8) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
comp4.x = {};
|
||||
comp5.x = {};
|
||||
comp6.x = {};
|
||||
comp7.x = {};
|
||||
comp8.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, IterateTenComponentsPersistent1M) {
|
||||
@@ -373,9 +507,25 @@ TEST(Benchmark, IterateTenComponentsPersistent1M) {
|
||||
registry.assign<Comp<8>>(entity);
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>(entt::persistent_t{}).each([](auto, auto &...) {});
|
||||
timer.elapsed();
|
||||
auto test = [®istry](auto func) {
|
||||
Timer timer;
|
||||
registry.view<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>(entt::persistent_t{}).each(func);
|
||||
timer.elapsed();
|
||||
};
|
||||
|
||||
test([](auto, const auto &...) {});
|
||||
test([](auto, auto &position, auto &velocity, auto &comp1, auto &comp2, auto &comp3, auto &comp4, auto &comp5, auto &comp6, auto &comp7, auto &comp8) {
|
||||
position.x = {};
|
||||
velocity.x = {};
|
||||
comp1.x = {};
|
||||
comp2.x = {};
|
||||
comp3.x = {};
|
||||
comp4.x = {};
|
||||
comp5.x = {};
|
||||
comp6.x = {};
|
||||
comp7.x = {};
|
||||
comp8.x = {};
|
||||
});
|
||||
}
|
||||
|
||||
TEST(Benchmark, SortSingle) {
|
||||
|
||||
Reference in New Issue
Block a user