Просмотр исходного кода

improvement: standard multi component view

Michele Caini 8 лет назад
Родитель
Сommit
bb4b868c79
3 измененных файлов с 44 добавлено и 30 удалено
  1. 6 6
      README.md
  2. 1 0
      TODO
  3. 37 24
      src/entt/entity/view.hpp

+ 6 - 6
README.md

@@ -192,17 +192,17 @@ Dell XPS 13 out of the mid 2014):
 | Create 10M entities | 0.1289s | **0.0423s** |
 | Destroy 10M entities | 0.0531s | **0.0221s** |
 | Standard view, 10M entities, one component | 0.0107s | **7.8e-08s** |
-| Standard view, 10M entities, two components | **0.0113s** | 0.0244s |
-| Standard view, 10M entities, two components<br/>Half of the entities have all the components | **0.0078s** | 0.0129s |
+| Standard view, 10M entities, two components | **0.0113s** | 0.0142s |
+| Standard view, 10M entities, two components<br/>Half of the entities have all the components | 0.0078s | **0.0072s** |
 | Standard view, 10M entities, two components<br/>One of the entities has all the components | 0.0071s | **5.5e-07s** |
 | Persistent view, 10M entities, two components | 0.0113s | **1.1e-07s** |
-| Standard view, 10M entities, five components | **0.0091s** | 0.0672s |
+| Standard view, 10M entities, five components | **0.0091s** | 0.0352s |
 | Persistent view, 10M entities, five components | 0.0091s | **2.5e-07s** |
-| Standard view, 10M entities, ten components | **0.0105s** | 0.1306s |
-| Standard view, 10M entities, ten components<br/>Half of the entities have all the components | **0.0090s** | 0.0629s |
+| Standard view, 10M entities, ten components | **0.0105s** | 0.0780s |
+| Standard view, 10M entities, ten components<br/>Half of the entities have all the components | **0.0090s** | 0.0407s |
 | Standard view, 10M entities, ten components<br/>One of the entities has all the components | 0.0070s | **1.3e-06s** |
 | Persistent view, 10M entities, ten components | 0.0105s | **5.0e-07s** |
-| Sort 150k entities, one component<br/>Arrays are in reverse order | - | **0.0043s** |
+| Sort 150k entities, one component<br/>Arrays are in reverse order | - | **0.0040s** |
 | Sort 150k entities, enforce permutation<br/>Arrays are in reverse order | - | **0.0006s** |
 
 `EnTT` includes its own tests and benchmarks. See

+ 1 - 0
TODO

@@ -3,4 +3,5 @@
 * to analyze, long term feature: systems organizer based on dependency graphs for implicit parallelism (I don't want to think anymore in future :-))
 * save/restore functionalities - see #27
 * parent-child relationships between entities directly managed by the registry. is it possible to do that in a clean and safe way?
+* standard multi component view: avoid testing (has) with candidates' pool
 * AOB

+ 37 - 24
src/entt/entity/view.hpp

@@ -2,6 +2,7 @@
 #define ENTT_ENTITY_VIEW_HPP
 
 
+#include <array>
 #include <tuple>
 #include <utility>
 #include <algorithm>
@@ -59,6 +60,7 @@ class PersistentView final {
     using pool_type = SparseSet<Entity, Comp>;
 
     using view_type = SparseSet<Entity>;
+    using pattern_type = std::tuple<pool_type<Component> &...>;
 
 public:
     /*! Input iterator type. */
@@ -302,7 +304,7 @@ public:
 
 private:
     view_type &view;
-    std::tuple<pool_type<Component> &...> pools;
+    pattern_type pools;
 };
 
 
@@ -351,25 +353,23 @@ class View final {
     template<typename Comp>
     using pool_type = SparseSet<Entity, Comp>;
 
-    using base_pool_type = SparseSet<Entity>;
-    using underlying_iterator_type = typename base_pool_type::iterator_type;
-    using repo_type = std::tuple<pool_type<Component> &...>;
+    using view_type = SparseSet<Entity>;
+    using underlying_iterator_type = typename view_type::iterator_type;
+    using unchecked_type = std::array<const view_type *, (sizeof...(Component) - 1)>;
+    using pattern_type = std::tuple<pool_type<Component> &...>;
 
     class Iterator {
         inline bool valid() const noexcept {
-            using accumulator_type = bool[];
-            const auto entity = *begin;
-            bool all = true;
-            accumulator_type accumulator =  { all, (all = all && std::get<pool_type<Component> &>(pools).has(entity))... };
-            (void)accumulator;
-            return all;
+            auto i = unchecked.size();
+            for(const auto entity = *begin; i && unchecked[i-1]->has(entity); --i);
+            return !i;
         }
 
     public:
-        using value_type = typename base_pool_type::entity_type;
+        using value_type = typename view_type::entity_type;
 
-        Iterator(const repo_type &pools, underlying_iterator_type begin, underlying_iterator_type end) noexcept
-            : pools{pools}, begin{begin}, end{end}
+        Iterator(unchecked_type unchecked, underlying_iterator_type begin, underlying_iterator_type end) noexcept
+            : unchecked{unchecked}, begin{begin}, end{end}
         {
             if(begin != end && !valid()) {
                 ++(*this);
@@ -398,7 +398,7 @@ class View final {
         }
 
     private:
-        const repo_type &pools;
+        unchecked_type unchecked;
         underlying_iterator_type begin;
         underlying_iterator_type end;
     };
@@ -407,16 +407,16 @@ public:
     /*! Input iterator type. */
     using iterator_type = Iterator;
     /*! @brief Underlying entity identifier. */
-    using entity_type = typename base_pool_type::entity_type;
+    using entity_type = typename view_type::entity_type;
     /*! @brief Unsigned integer type. */
-    using size_type = typename base_pool_type::size_type;
+    using size_type = typename view_type::size_type;
 
     /**
      * @brief Constructs a view out of a bunch of pools of components.
      * @param pools References to pools of components.
      */
     View(pool_type<Component>&... pools) noexcept
-        : pools{pools...}, view{nullptr}
+        : pools{pools...}, view{nullptr}, unchecked{}
     {
         reset();
     }
@@ -436,7 +436,7 @@ public:
      * @return An iterator to the first entity that has the given components.
      */
     iterator_type begin() const noexcept {
-        return Iterator{pools, view->begin(), view->end()};
+        return Iterator{unchecked, view->begin(), view->end()};
     }
 
     /**
@@ -455,7 +455,7 @@ public:
      * given components.
      */
     iterator_type end() const noexcept {
-        return Iterator{pools, view->end(), view->end()};
+        return Iterator{unchecked, view->end(), view->end()};
     }
 
     /**
@@ -604,15 +604,28 @@ public:
      */
     void reset() {
         using accumulator_type = size_type[];
-        auto probe = [this](auto sz, auto &pool) { return pool.size() < sz ? (view = &pool, pool.size()) : sz; };
         size_type sz = std::max({ std::get<pool_type<Component> &>(pools).size()... }) + std::size_t{1};
-        accumulator_type accumulator = { sz, (sz = probe(sz, std::get<pool_type<Component> &>(pools)))... };
-        (void)accumulator;
+        size_type pos{};
+
+        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;
+        };
+
+        accumulator_type probing = { (sz = probe(sz, std::get<pool_type<Component> &>(pools)))... };
+        accumulator_type filtering = { (pos = filter(pos, std::get<pool_type<Component> &>(pools)))... };
+
+        (void)filtering;
+        (void)probing;
     }
 
 private:
-    repo_type pools;
-    base_pool_type *view;
+    pattern_type pools;
+    const view_type *view;
+    unchecked_type unchecked;
 };