diff --git a/include/xo/arena/MemorySizeInfo.hpp b/include/xo/arena/MemorySizeInfo.hpp index 37b5ce0..a9649b3 100644 --- a/include/xo/arena/MemorySizeInfo.hpp +++ b/include/xo/arena/MemorySizeInfo.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include #include #include @@ -12,14 +13,27 @@ namespace xo { namespace mm { + struct MemorySizeDetail { + using typeseq = xo::reflect::typeseq; + + /** identifies a c++ type T. See xo/facet/TypeRegistry **/ + typeseq tseq_; + /** number of T-instances **/ + uint32_t n_alloc_ = 0; + /** bytes used by T-instances **/ + uint32_t z_alloc_ = 0; + }; + struct MemorySizeInfo { using size_type = std::size_t; + using DetailArrayType = std::array; MemorySizeInfo() = default; MemorySizeInfo(std::string_view name, - std::size_t u, std::size_t a, std::size_t c, std::size_t r) + std::size_t u, std::size_t a, std::size_t c, std::size_t r, + DetailArrayType * detail) : resource_name_{name}, - used_{u}, allocated_{a}, committed_{c}, reserved_{r} + used_{u}, allocated_{a}, committed_{c}, reserved_{r}, detail_{detail} {} static MemorySizeInfo sentinel() { return MemorySizeInfo(); } @@ -36,6 +50,9 @@ namespace xo { * virtual memory addresses range obtained, whether or not committed **/ std::size_t reserved_ = 0; + + /** optional histogram with per-data-type counts **/ + DetailArrayType * detail_ = nullptr; }; /** function that visits MemorySizeInfo for a collection of @p n memory pools. diff --git a/src/arena/DArena.cpp b/src/arena/DArena.cpp index 72d8cbf..2cd36dc 100644 --- a/src/arena/DArena.cpp +++ b/src/arena/DArena.cpp @@ -176,11 +176,43 @@ namespace xo { * must assume it's all used **/ + // assemble histogram + MemorySizeInfo::DetailArrayType detail_v; + MemorySizeInfo::DetailArrayType * p_detail = nullptr; + + if (config_.store_header_flag_) { + p_detail = &detail_v; + + for (const auto & ix : *this) { + typeseq ix_tseq(ix.tseq()); + + // totals in detail_v[0] + MemorySizeDetail & d = detail_v[0]; + ++d.n_alloc_; + d.z_alloc_ += ix.size(); + + // O(n) insertion here + for (size_t i = 1; i < detail_v.size(); ++i) { + if (detail_v[i].tseq_.is_sentinel() + || (detail_v[i].tseq_ == ix_tseq)) + { + MemorySizeDetail & d = detail_v[i]; + + d.tseq_ = ix_tseq; + ++d.n_alloc_; + d.z_alloc_ += ix.size(); + break; + } + } + } + } + fn(MemorySizeInfo(config_.name_, this->allocated() /*used*/, this->allocated(), this->committed(), - this->reserved())); + this->reserved(), + p_detail)); } AllocInfo diff --git a/src/arena/DCircularBuffer.cpp b/src/arena/DCircularBuffer.cpp index e5b1c72..bd4dc0c 100644 --- a/src/arena/DCircularBuffer.cpp +++ b/src/arena/DCircularBuffer.cpp @@ -86,7 +86,8 @@ namespace xo { occupied_range_.size() /*used*/, occupied_range_.size(), mapped_range_.size(), - reserved_range_.size())); + reserved_range_.size(), + nullptr /*detail*/)); pinned_spans_.visit_pools(visitor); }