perf improvement

This commit is contained in:
Michele Caini
2019-08-17 15:51:22 +02:00
parent 12ac858242
commit effe477351
2 changed files with 50 additions and 48 deletions

View File

@@ -233,10 +233,9 @@ class basic_registry {
// lengthens the implicit list of destroyed entities
const auto entt = to_integer(entity) & traits_type::entity_mask;
const auto version = ((to_integer(entity) >> traits_type::entity_shift) + 1) << traits_type::entity_shift;
const auto node = to_integer(next) | version;
const auto node = to_integer(destroyed) | version;
entities[entt] = Entity{node};
next = Entity{entt};
++available;
destroyed = Entity{entt};
}
template<typename Component>
@@ -363,7 +362,15 @@ public:
* @return Number of entities still in use.
*/
size_type alive() const ENTT_NOEXCEPT {
return entities.size() - available;
auto curr = destroyed;
size_type cnt{};
while(curr != null) {
curr = entities[to_integer(curr) & traits_type::entity_mask];
++cnt;
}
return entities.size() - cnt;
}
/**
@@ -438,7 +445,7 @@ public:
* @return True if at least an entity is still in use, false otherwise.
*/
bool empty() const ENTT_NOEXCEPT {
return entities.size() == available;
return !alive();
}
/**
@@ -563,17 +570,16 @@ public:
decltype(auto) create() {
entity_type entity;
if(available) {
const auto entt = to_integer(next);
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
next = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
entity = entity_type{entt | version};
entities[entt] = entity;
--available;
} else {
if(destroyed == null) {
entity = entities.emplace_back(entity_type(entities.size()));
// traits_type::entity_mask is reserved to allow for null identifiers
ENTT_ASSERT(to_integer(entity) < traits_type::entity_mask);
} else {
const auto entt = to_integer(destroyed);
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
destroyed = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
entity = entity_type{entt | version};
entities[entt] = entity;
}
if constexpr(sizeof...(Component) == 0) {
@@ -599,20 +605,20 @@ public:
template<typename... Component, typename It>
auto create(It first, It last) {
static_assert(std::is_convertible_v<entity_type, typename std::iterator_traits<It>::value_type>);
const auto length = size_type(std::distance(first, last));
const auto sz = std::min(available, length);
available -= sz;
std::generate(first, last, [this]() {
entity_type curr;
const auto tail = std::generate_n(first, sz, [this]() mutable {
const auto entt = to_integer(next);
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
next = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
return (entities[entt] = entity_type{entt | version});
});
if(destroyed != null) {
const auto entt = to_integer(destroyed);
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
destroyed = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
curr = (entities[entt] = entity_type{entt | version});
} else {
curr = entities.emplace_back(entity_type(entities.size()));
}
std::generate(tail, last, [this]() {
return entities.emplace_back(entity_type(entities.size()));
return curr;
});
if constexpr(sizeof...(Component) > 0) {
@@ -1162,7 +1168,11 @@ public:
void each(Func func) const {
static_assert(std::is_invocable_v<Func, entity_type>);
if(available) {
if(destroyed == null) {
for(auto pos = entities.size(); pos; --pos) {
func(entities[pos-1]);
}
} else {
for(auto pos = entities.size(); pos; --pos) {
const auto curr = entity_type(pos - 1);
const auto entity = entities[to_integer(curr)];
@@ -1172,10 +1182,6 @@ public:
func(entity);
}
}
} else {
for(auto pos = entities.size(); pos; --pos) {
func(entities[pos-1]);
}
}
}
@@ -1495,9 +1501,8 @@ public:
}
other.skip_family_pools = skip_family_pools;
other.destroyed = destroyed;
other.entities = entities;
other.available = available;
other.next = next;
other.pools.erase(std::remove_if(other.pools.begin()+skip_family_pools, other.pools.end(), [](const auto &pdata) {
return !pdata.pool;
@@ -1569,10 +1574,8 @@ public:
entt::basic_snapshot<Entity> snapshot() const ENTT_NOEXCEPT {
using follow_fn_type = entity_type(const basic_registry &, const entity_type);
const auto head = to_integer(next);
const entity_type seed = available
? entity_type{head | (to_integer(entities[head]) & (traits_type::version_mask << traits_type::entity_shift))}
: next;
const auto head = to_integer(destroyed);
const entity_type seed = destroyed == null ? destroyed : entity_type{head | (to_integer(entities[head]) & (traits_type::version_mask << traits_type::entity_shift))};
follow_fn_type *follow = [](const basic_registry &reg, const entity_type entity) -> entity_type {
const auto &others = reg.entities;
@@ -1602,7 +1605,7 @@ public:
basic_snapshot_loader<Entity> loader() ENTT_NOEXCEPT {
using force_fn_type = void(basic_registry &, const entity_type, const bool);
force_fn_type *force = [](basic_registry &reg, const entity_type entity, const bool destroyed) {
force_fn_type *force = [](basic_registry &reg, const entity_type entity, const bool discard) {
const auto entt = to_integer(entity) & traits_type::entity_mask;
auto &others = reg.entities;
@@ -1617,7 +1620,7 @@ public:
others[entt] = entity;
if(destroyed) {
if(discard) {
reg.destroy(entity);
const auto version = to_integer(entity) & (traits_type::version_mask << traits_type::entity_shift);
others[entt] = entity_type{(to_integer(others[entt]) & traits_type::entity_mask) | version};
@@ -1742,8 +1745,7 @@ private:
std::vector<group_data> groups{};
std::vector<ctx_variable> vars{};
std::vector<entity_type> entities{};
size_type available{};
entity_type next{null};
entity_type destroyed{null};
};

View File

@@ -211,14 +211,14 @@ class basic_snapshot_loader {
}
template<typename Archive>
void assure(Archive &archive, bool destroyed) const {
void assure(Archive &archive, bool discard) const {
typename traits_type::entity_type length{};
archive(length);
while(length--) {
Entity entt{};
archive(entt);
force(*reg, entt, destroyed);
force(*reg, entt, discard);
}
}
@@ -228,17 +228,17 @@ class basic_snapshot_loader {
archive(length);
while(length--) {
static constexpr auto destroyed = false;
static constexpr auto discard = false;
Entity entt{};
if constexpr(std::is_empty_v<Type>) {
archive(entt);
force(*reg, entt, destroyed);
force(*reg, entt, discard);
reg->template assign<Type>(args..., entt);
} else {
Type instance{};
archive(entt, instance);
force(*reg, entt, destroyed);
force(*reg, entt, discard);
reg->template assign<Type>(args..., entt, std::as_const(instance));
}
}
@@ -263,8 +263,8 @@ public:
*/
template<typename Archive>
const basic_snapshot_loader & entities(Archive &archive) const {
static constexpr auto destroyed = false;
assure(archive, destroyed);
static constexpr auto discard = false;
assure(archive, discard);
return *this;
}
@@ -280,8 +280,8 @@ public:
*/
template<typename Archive>
const basic_snapshot_loader & destroyed(Archive &archive) const {
static constexpr auto destroyed = true;
assure(archive, destroyed);
static constexpr auto discard = true;
assure(archive, discard);
return *this;
}