From d93427fb52e4418e91f665f88db8869811d0d3e1 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 12 Apr 2019 20:10:12 +0700 Subject: [PATCH] memory usage stats --- ecs.hpp | 45 +++++++++++++++++++++++++++++++ ecs_tests.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/ecs.hpp b/ecs.hpp index 6224264..9d10a25 100644 --- a/ecs.hpp +++ b/ecs.hpp @@ -426,6 +426,11 @@ namespace ecs_hpp std::size_t size() const noexcept { return dense_.size(); } + + std::size_t memory_usage() const noexcept { + return dense_.capacity() * sizeof(dense_[0]) + + sparse_.capacity() * sizeof(sparse_[0]); + } private: Indexer indexer_; std::vector dense_; @@ -595,6 +600,11 @@ namespace ecs_hpp std::size_t size() const noexcept { return values_.size(); } + + std::size_t memory_usage() const noexcept { + return keys_.memory_usage() + + values_.capacity() * sizeof(values_[0]); + } private: sparse_set keys_; std::vector values_; @@ -646,6 +656,7 @@ namespace ecs_hpp virtual bool remove(entity_id id) noexcept = 0; virtual bool has(entity_id id) const noexcept = 0; virtual void clone(entity_id from, entity_id to) = 0; + virtual std::size_t memory_usage() const noexcept = 0; }; template < typename T > @@ -669,6 +680,8 @@ namespace ecs_hpp void for_each_component(F&& f); template < typename F > void for_each_component(F&& f) const; + + std::size_t memory_usage() const noexcept override; private: registry& owner_; detail::sparse_map components_; @@ -738,6 +751,11 @@ namespace ecs_hpp f(id, components_.get(id)); } } + + template < typename T > + std::size_t component_storage::memory_usage() const noexcept { + return components_.memory_usage(); + } } } @@ -1234,6 +1252,15 @@ namespace ecs_hpp void process_systems_above(priority_t min); void process_systems_below(priority_t max); void process_systems_in_range(priority_t min, priority_t max); + + struct memory_usage_info { + std::size_t entities{0u}; + std::size_t components{0u}; + }; + memory_usage_info memory_usage() const noexcept; + + template < typename T > + std::size_t component_memory_usage() const noexcept; private: template < typename T > detail::component_storage* find_storage_() noexcept; @@ -2217,6 +2244,24 @@ namespace ecs_hpp } } + inline registry::memory_usage_info registry::memory_usage() const noexcept { + memory_usage_info info; + info.entities += free_entity_ids_.capacity() * sizeof(free_entity_ids_[0]); + info.entities += entity_ids_.memory_usage(); + for ( const auto family_id : storages_ ) { + info.components += storages_.get(family_id)->memory_usage(); + } + return info; + } + + template < typename T > + std::size_t registry::component_memory_usage() const noexcept { + const detail::component_storage* storage = find_storage_(); + return storage + ? storage->memory_usage() + : 0u; + } + template < typename T > detail::component_storage* registry::find_storage_() noexcept { const auto family = detail::type_family::id(); diff --git a/ecs_tests.cpp b/ecs_tests.cpp index 9299464..0f6c56b 100644 --- a/ecs_tests.cpp +++ b/ecs_tests.cpp @@ -1154,6 +1154,79 @@ TEST_CASE("registry") { REQUIRE(e2.get_component().i == 5); } } + SECTION("memory_usage") { + { + ecs::registry w; + REQUIRE(w.memory_usage().entities == 0u); + + auto e1 = w.create_entity(); + auto e2 = w.create_entity(); + + const std::size_t expected_usage = + 2 * sizeof(ecs::entity_id) + // vector free entity ids + 4 * sizeof(std::size_t) + // sparse entity ids (keys) + 2 * sizeof(ecs::entity_id); // sparse entity ids (values) + REQUIRE(w.memory_usage().entities == expected_usage); + + e1.destroy(); + e2.destroy(); + REQUIRE(w.memory_usage().entities == expected_usage); + + e1 = w.create_entity(); + e2 = w.create_entity(); + REQUIRE(w.memory_usage().entities == expected_usage); + } + { + ecs::registry w; + + auto e1 = w.create_entity(); + e1.assign_component(1, 2); + + auto e2 = w.create_entity(); + e2.assign_component(1, 2); + + const std::size_t expected_usage = + 2 * sizeof(position_c) + // vector values + 4 * sizeof(std::size_t) + // sparse keys (keys) + 2 * sizeof(ecs::entity_id); // sparse keys (values) + REQUIRE(w.memory_usage().components == expected_usage); + + REQUIRE(w.component_memory_usage() == + 2 * sizeof(position_c) + + 4 * sizeof(std::size_t) + + 2 * sizeof(ecs::entity_id)); + + REQUIRE_FALSE(w.component_memory_usage()); + } + { + ecs::registry w; + + auto e1 = w.create_entity(); + e1.assign_component(1, 2); + + auto e2 = w.create_entity(); + e2.assign_component(3, 4); + + const std::size_t expected_usage = + sizeof(position_c) + + 2 * sizeof(std::size_t) + + 1 * sizeof(ecs::entity_id) + + sizeof(velocity_c) + + 3 * sizeof(std::size_t) + + 1 * sizeof(ecs::entity_id); + REQUIRE(w.memory_usage().components == expected_usage); + + REQUIRE(w.component_memory_usage() == + sizeof(position_c) + + 2 * sizeof(std::size_t) + + 1 * sizeof(ecs::entity_id)); + + REQUIRE(w.component_memory_usage() == + sizeof(velocity_c) + + 3 * sizeof(std::size_t) + + 1 * sizeof(ecs::entity_id)); + } + } } TEST_CASE("example") {