Browse Source

perf improvement

Michele Caini 6 years ago
parent
commit
effe477351
2 changed files with 50 additions and 48 deletions
  1. 41 39
      src/entt/entity/registry.hpp
  2. 9 9
      src/entt/entity/snapshot.hpp

+ 41 - 39
src/entt/entity/registry.hpp

@@ -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};
 };
 
 

+ 9 - 9
src/entt/entity/snapshot.hpp

@@ -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;
     }