diff --git a/xo-arena/include/xo/arena/MemorySizeInfo.hpp b/xo-arena/include/xo/arena/MemorySizeInfo.hpp index 37b5ce08..a9649b3e 100644 --- a/xo-arena/include/xo/arena/MemorySizeInfo.hpp +++ b/xo-arena/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/xo-arena/src/arena/DArena.cpp b/xo-arena/src/arena/DArena.cpp index 72d8cbf7..2cd36dc1 100644 --- a/xo-arena/src/arena/DArena.cpp +++ b/xo-arena/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/xo-arena/src/arena/DCircularBuffer.cpp b/xo-arena/src/arena/DCircularBuffer.cpp index e5b1c725..bd4dc0cd 100644 --- a/xo-arena/src/arena/DCircularBuffer.cpp +++ b/xo-arena/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); } diff --git a/xo-expression2/include/xo/expression2/GlobalSymtab.hpp b/xo-expression2/include/xo/expression2/GlobalSymtab.hpp new file mode 100644 index 00000000..0c0dabf4 --- /dev/null +++ b/xo-expression2/include/xo/expression2/GlobalSymtab.hpp @@ -0,0 +1,13 @@ +/** @file GlobalSymtab.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "DGlobalSymtab.hpp" +//#include "symtab/ISymbolTable_DGlobalSymtab.hpp" +//#include "symtab/IGCObject_DGlobalSymtab.hpp" +//#include "symtab/IPrintable_DGlobalSymtab.hpp" + +/* end GlobalSymtab.hpp */ diff --git a/xo-expression2/src/expression2/expression2_register_facets.cpp b/xo-expression2/src/expression2/expression2_register_facets.cpp index 16bfac2a..f14ceae6 100644 --- a/xo-expression2/src/expression2/expression2_register_facets.cpp +++ b/xo-expression2/src/expression2/expression2_register_facets.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ namespace xo { using xo::mm::AGCObject; using xo::print::APrintable; using xo::facet::FacetRegistry; + using xo::facet::TypeRegistry; using xo::facet::typeseq; namespace scm { @@ -45,6 +47,8 @@ namespace xo { { scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -58,10 +62,6 @@ namespace xo { // +- IfElseExpr // \- SequenceExpr - // SymbolTable - // +- LocalSymtab - // \- GlobalSymtab - FacetRegistry::register_impl(); FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -94,10 +94,17 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + // SymbolTable + // +- LocalSymtab + // \- GlobalSymtab + FacetRegistry::register_impl(); FacetRegistry::register_impl(); FacetRegistry::register_impl(); + // until we register facets + TypeRegistry::register_type(); + log && log(xtag("DUniqueString.tseq", typeseq::id())); log && log(xtag("DDefineExpr.tseq", typeseq::id())); log && log(xtag("DVariable.tseq", typeseq::id())); @@ -108,6 +115,7 @@ namespace xo { log && log(xtag("DIfElseExpr.tseq", typeseq::id())); log && log(xtag("DSequenceExpr.tseq", typeseq::id())); + log && log(xtag("DGlobalSymtab.tseq", typeseq::id())); log && log(xtag("DLocalSymtab.tseq", typeseq::id())); log && log(xtag("AExpression.tseq", typeseq::id())); diff --git a/xo-facet/include/xo/facet/TypeRegistry.hpp b/xo-facet/include/xo/facet/TypeRegistry.hpp index 19091630..1f3cb2be 100644 --- a/xo-facet/include/xo/facet/TypeRegistry.hpp +++ b/xo-facet/include/xo/facet/TypeRegistry.hpp @@ -53,13 +53,13 @@ namespace xo { instance()._register_type(r); } - /** Number of registered (facet, repr) pairs **/ - std::size_t size() const { return registry_.size(); } - - std::string_view id2name(typeseq id) const noexcept { + static std::string_view id2name(typeseq id) noexcept { return instance()._id2name(id); } + /** Number of registered (facet, repr) pairs **/ + std::size_t size() const { return registry_.size(); } + /** visit memory pools owned by facet registry **/ void visit_pools(const MemorySizeVisitor & visitor) { registry_.visit_pools(visitor); diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index 2f2272ab..46385c56 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace xo { @@ -55,17 +56,23 @@ namespace xo { ParserFixture(const std::string & testname, bool debug_flag) { this->aux_arena_ - = std::move(DArena(ArenaConfig().with_name(testname).with_size(4 * 1024))); + = std::move(DArena(ArenaConfig() + .with_name(testname) + .with_size(4 * 1024))); obj aux_mm(&aux_arena_); this->expr_arena_ = dp::make(aux_mm, - ArenaConfig().with_name("expr").with_size(16 * 1024)); + (ArenaConfig() + .with_name("expr") + .with_size(16 * 1024) + .with_store_header_flag(true))); obj expr_mm(expr_arena_.data()); ParserConfig cfg; cfg.parser_arena_config_.size_ = 16 * 1024; - cfg.symtab_config_.hint_max_capacity_ = 512; + /* editor bait: symbol table */ + cfg.symtab_config_.hint_max_capacity_ = 128; cfg.max_stringtable_capacity_ = 512; cfg.debug_flag_ = false; @@ -77,12 +84,32 @@ namespace xo { ParserFixture(const ParserFixture && other) = delete; bool log_memory_layout(scope * p_log) { + using xo::facet::TypeRegistry; + using xo::mm::MemorySizeDetail; + auto visitor = [p_log](const MemorySizeInfo & info) { - *p_log && (*p_log)(xtag("name", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), + *p_log && (*p_log)(xtag("name", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), xtag("commit", info.committed_), - xtag("resv", info.reserved_)); + xtag("resv", info.reserved_)); + if (*p_log && info.detail_) { + (*p_log)("detail", + xtag("n", (*info.detail_)[0].n_alloc_), + xtag("z", (*info.detail_)[0].z_alloc_)); + for (size_t i = 1; i < info.detail_->size(); ++i) { + const MemorySizeDetail & d = (*info.detail_)[i]; + + if (d.tseq_.is_sentinel()) + break; + + (*p_log)("[",i,"]", + xtag("tseq",d.tseq_), + xtag("type", TypeRegistry::id2name(d.tseq_)), + xtag("n", d.n_alloc_), + xtag("z", d.z_alloc_)); + } + } }; aux_arena_.visit_pools(visitor); @@ -144,14 +171,29 @@ namespace xo { REQUIRE(parser.debug_flag() == false); REQUIRE(parser.is_at_toplevel() == true); + // baseline: + // SchematikaParser-ctor :used 1408 + // facets-ctl :used 73 // facet hashtable + // facets-slots :used 1168 // facet hashtable + // expr :used 2056 + // [1] :type xo::scm::DArray :n 1 :z 2056 // DArray of DUniqueString* + // [2] :type ? :n 1 : z 16 + // strings :used 0 + // stringkeys-ctl :used 0 + // strinkeys-slots :used 0 + // parser-arena :used 0 + // global-symtab-ctl :used 0 + // global-symtab-slots :used 0 + log && fixture.log_memory_layout(&log); } - TEST_CASE("SchematikaParser-begin-interactive", "[reader2][SchematikaParser]") + TEST_CASE("SchematikaParser-begin-interactive", + "[reader2][SchematikaParser]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - constexpr bool c_debug_flag = false; + constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); ParserFixture fixture(testname, c_debug_flag); @@ -697,7 +739,7 @@ namespace xo { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - constexpr bool c_debug_flag = true; + constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); ParserFixture fixture(testname, c_debug_flag); diff --git a/xo-reflectutil/include/xo/reflectutil/typeseq.hpp b/xo-reflectutil/include/xo/reflectutil/typeseq.hpp index 336f011c..d337cd5b 100644 --- a/xo-reflectutil/include/xo/reflectutil/typeseq.hpp +++ b/xo-reflectutil/include/xo/reflectutil/typeseq.hpp @@ -61,7 +61,7 @@ namespace xo { } private: - int32_t seqno_ = 0; + int32_t seqno_ = -1; std::string_view name_; }; @@ -91,10 +91,11 @@ namespace xo { return typeseq(xo::reflect::typerecd::recd().seqno()); } + bool is_sentinel() const { return seqno_ == -1; } int32_t seqno() const { return seqno_; } private: - int32_t seqno_ = 0; + int32_t seqno_ = -1; }; //template