diff --git a/include/UECS/Schedule.h b/include/UECS/Schedule.h index 1d7f4a5..c2dad5a 100644 --- a/include/UECS/Schedule.h +++ b/include/UECS/Schedule.h @@ -1,12 +1,14 @@ #pragma once -#include "details/SystemFunc.h" +#include "SystemFunc.h" #include "details/Job.h" #include #include #include +#include + namespace Ubpa::UECS::details { struct Compiler; } @@ -36,7 +38,7 @@ namespace Ubpa::UECS { template const SystemFunc* RegisterEntityJob( Func&&, - std::string name, + std::string_view name, bool isParallel = true, ArchetypeFilter = {}, CmptLocator = {}, @@ -52,7 +54,7 @@ namespace Ubpa::UECS { template const SystemFunc* RegisterChunkJob( Func&&, - std::string name, + std::string_view name, ArchetypeFilter = {}, bool isParallel = true, SingletonLocator = {}, @@ -66,7 +68,7 @@ namespace Ubpa::UECS { template const SystemFunc* RegisterJob( Func&&, - std::string name, + std::string_view name, SingletonLocator = {}, RandomAccessor = {} ); @@ -82,6 +84,8 @@ namespace Ubpa::UECS { // clear every frame std::pmr::monotonic_buffer_resource* GetFrameMonotonicResource() { return &frame_rsrc; } + template + T* CreateFrameObject(Args&&... args) const; ~Schedule(); private: @@ -91,14 +95,24 @@ namespace Ubpa::UECS { void Clear(); struct CmptSysFuncs { - std::vector lastFrameSysFuncs; - std::vector writeSysFuncs; - std::vector latestSysFuncs; + CmptSysFuncs(std::pmr::memory_resource* rsrc) : + lastFrameSysFuncs{ std::pmr::vector(std::pmr::polymorphic_allocator{rsrc}) }, + writeSysFuncs{ std::pmr::vector(std::pmr::polymorphic_allocator{rsrc}) }, + latestSysFuncs{ std::pmr::vector(std::pmr::polymorphic_allocator{rsrc}) } {} + + pmr::small_vector lastFrameSysFuncs; + pmr::small_vector writeSysFuncs; + pmr::small_vector latestSysFuncs; }; friend struct details::Compiler; - std::unordered_map GenCmptSysFuncsMap() const; - SysFuncGraph GenSysFuncGraph() const; + using CmptSysFuncsMap = std::pmr::unordered_map; + + // use frame_rsrc, so no need to delete + CmptSysFuncsMap* GenCmptSysFuncsMap() const; + + // use frame_rsrc, so no need to delete + SysFuncGraph* GenSysFuncGraph() const; // SystemFunc's hashcode to pointer of SystemFunc std::unordered_map sysFuncs; @@ -115,7 +129,8 @@ namespace Ubpa::UECS { std::map>> commandBuffer; - std::pmr::monotonic_buffer_resource frame_rsrc; // release in every frame + mutable std::pmr::monotonic_buffer_resource frame_rsrc; // release in every frame + std::string_view RegisterFrameString(std::string_view str); friend class World; }; diff --git a/include/UECS/details/SystemFunc.h b/include/UECS/SystemFunc.h similarity index 76% rename from include/UECS/details/SystemFunc.h rename to include/UECS/SystemFunc.h index 58bfbd1..311731c 100644 --- a/include/UECS/details/SystemFunc.h +++ b/include/UECS/SystemFunc.h @@ -1,12 +1,12 @@ #pragma once -#include "../EntityQuery.h" -#include "../SingletonLocator.h" -#include "../RandomAccessor.h" -#include "../Entity.h" -#include "../CmptsView.h" -#include "../SingletonsView.h" -#include "../ChunkView.h" +#include "EntityQuery.h" +#include "SingletonLocator.h" +#include "RandomAccessor.h" +#include "Entity.h" +#include "CmptsView.h" +#include "SingletonsView.h" +#include "ChunkView.h" #include @@ -42,17 +42,17 @@ namespace Ubpa::UECS { // Mode::Entity template - SystemFunc(Func&&, std::string name, ArchetypeFilter, CmptLocator, SingletonLocator, RandomAccessor, bool isParallel); + SystemFunc(Func&&, std::string_view name, ArchetypeFilter, CmptLocator, SingletonLocator, RandomAccessor, bool isParallel); // Mode::Chunk template - SystemFunc(Func&&, std::string name, ArchetypeFilter, SingletonLocator, RandomAccessor, bool isParallel); + SystemFunc(Func&&, std::string_view name, ArchetypeFilter, SingletonLocator, RandomAccessor, bool isParallel); // Mode::Job template - SystemFunc(Func&&, std::string name, SingletonLocator, RandomAccessor); + SystemFunc(Func&&, std::string_view name, SingletonLocator, RandomAccessor); - const std::string& Name() const noexcept { return name; } + std::string_view Name() const noexcept { return name; } static constexpr std::size_t GetValue(std::string_view name) noexcept { return string_hash(name); } @@ -68,11 +68,11 @@ namespace Ubpa::UECS { bool operator==(const SystemFunc& sysFunc) const noexcept { return name == sysFunc.name; } private: Mode mode; - std::string name; + std::string_view name; std::size_t hashCode; // after name bool isParallel; std::function func; }; } -#include "SystemFunc.inl" +#include "details/SystemFunc.inl" diff --git a/include/UECS/details/Schedule.inl b/include/UECS/details/Schedule.inl index 2f90548..fbcb33e 100644 --- a/include/UECS/details/Schedule.inl +++ b/include/UECS/details/Schedule.inl @@ -1,10 +1,16 @@ #pragma once namespace Ubpa::UECS { + template + T* Schedule::CreateFrameObject(Args&&... args) const { + void* buffer = frame_rsrc.allocate(sizeof(T), alignof(T)); + return new(buffer)T(std::forward(args)...); + } + template const SystemFunc* Schedule::RegisterEntityJob( Func&& func, - std::string name, + std::string_view name, bool isParallel, ArchetypeFilter filter, CmptLocator cmptLocator, @@ -13,7 +19,7 @@ namespace Ubpa::UECS { ) { return Request( std::forward(func), - std::move(name), + RegisterFrameString(name), std::move(filter), std::move(cmptLocator), std::move(singletonLocator), @@ -25,7 +31,7 @@ namespace Ubpa::UECS { template const SystemFunc* Schedule::RegisterChunkJob( Func&& func, - std::string name, + std::string_view name, ArchetypeFilter filter, bool isParallel, SingletonLocator singletonLocator, @@ -33,7 +39,7 @@ namespace Ubpa::UECS { ) { return Request( std::forward(func), - std::move(name), + RegisterFrameString(name), std::move(filter), std::move(singletonLocator), std::move(randomAccessor), @@ -44,13 +50,13 @@ namespace Ubpa::UECS { template const SystemFunc* Schedule::RegisterJob( Func&& func, - std::string name, + std::string_view name, SingletonLocator singletonLocator, RandomAccessor randomAccessor ) { return Request( std::forward(func), - std::move(name), + RegisterFrameString(name), std::move(singletonLocator), std::move(randomAccessor) ); diff --git a/include/UECS/details/SystemFunc.inl b/include/UECS/details/SystemFunc.inl index bd6cba1..f29d1cb 100644 --- a/include/UECS/details/SystemFunc.inl +++ b/include/UECS/details/SystemFunc.inl @@ -12,7 +12,7 @@ namespace Ubpa::UECS { template SystemFunc::SystemFunc( Func&& func, - std::string name, + std::string_view name, ArchetypeFilter archetypeFilter, CmptLocator cmptLocator, SingletonLocator singletonLocator, @@ -23,7 +23,7 @@ namespace Ubpa::UECS { singletonLocator{ std::move(singletonLocator.Combine()) }, randomAccessor{std::move(randomAccessor)}, mode{ Mode::Entity }, - name{ std::move(name) }, + name{ name }, hashCode{ GetValue(this->name) }, isParallel{ isParallel }, func{ details::Pack(std::forward(func)) } @@ -43,7 +43,7 @@ namespace Ubpa::UECS { template SystemFunc::SystemFunc( Func&& func, - std::string name, + std::string_view name, ArchetypeFilter archetypeFilter, SingletonLocator singletonLocator, RandomAccessor randomAccessor, @@ -53,7 +53,7 @@ namespace Ubpa::UECS { singletonLocator{ std::move(singletonLocator.Combine()) }, randomAccessor{ std::move(randomAccessor) }, mode{ Mode::Chunk }, - name{ std::move(name) }, + name{ name }, hashCode{ GetValue(this->name) }, isParallel{ isParallel }, func{ details::Pack(std::forward(func)) } @@ -80,12 +80,12 @@ namespace Ubpa::UECS { // Mode::Job template - SystemFunc::SystemFunc(Func&& func, std::string name, SingletonLocator singletonLocator, RandomAccessor randomAccessor) + SystemFunc::SystemFunc(Func&& func, std::string_view name, SingletonLocator singletonLocator, RandomAccessor randomAccessor) : singletonLocator{ std::move(singletonLocator.Combine()) }, randomAccessor {std::move(randomAccessor)}, mode{ Mode::Job }, - name{ std::move(name) }, + name{ name }, hashCode{ GetValue(this->name) }, isParallel{ false }, func{ details::Pack(std::forward(func)) } diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index 4cbc9c2..c8e7c63 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -2,7 +2,7 @@ #include "Archetype.h" -#include +#include #include using namespace Ubpa::UECS; diff --git a/src/core/Schedule.cpp b/src/core/Schedule.cpp index 11554cf..04fc847 100644 --- a/src/core/Schedule.cpp +++ b/src/core/Schedule.cpp @@ -10,6 +10,13 @@ Schedule::~Schedule() { Clear(); } +std::string_view Schedule::RegisterFrameString(std::string_view str) { + auto* buffer = (char*)frame_rsrc.allocate((str.size() + 1) * sizeof(char), alignof(char)); + std::memcpy(buffer, str.data(), str.size() * sizeof(char)); + buffer[str.size()] = 0; + return str; +} + Schedule& Schedule::Order(string_view x, string_view y) { sysFuncOrder.emplace(SystemFunc::GetValue(x), SystemFunc::GetValue(y)); return *this; @@ -32,10 +39,11 @@ Schedule& Schedule::EraseNone(string_view sys, TypeID type) { } void Schedule::Clear() { - auto alloc = std::pmr::polymorphic_allocator{ &frame_rsrc }; + //auto alloc = std::pmr::polymorphic_allocator{ &frame_rsrc }; for (const auto& [hash, sysFunc] : sysFuncs) { sysFunc->~SystemFunc(); - alloc.deallocate(sysFunc, 1); + // no need to release + //alloc.deallocate(sysFunc, 1); } sysFuncs.clear(); sysFuncOrder.clear(); @@ -43,20 +51,22 @@ void Schedule::Clear() { frame_rsrc.release(); } -unordered_map Schedule::GenCmptSysFuncsMap() const { - unordered_map rst; +Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap() const { + CmptSysFuncsMap* rst = CreateFrameObject(CmptSysFuncsMap::allocator_type{ &frame_rsrc }); + for (const auto& [hashcode, sysFunc] : sysFuncs) { for (const auto& type : sysFunc->entityQuery.locator.AccessTypeIDs()) { + auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second; switch (type.GetAccessMode()) { case AccessMode::LAST_FRAME: - rst[type].lastFrameSysFuncs.push_back(sysFunc); + cmptSysFuncs.lastFrameSysFuncs.push_back(sysFunc); break; case AccessMode::WRITE: - rst[type].writeSysFuncs.push_back(sysFunc); + cmptSysFuncs.writeSysFuncs.push_back(sysFunc); break; case AccessMode::LATEST: - rst[type].latestSysFuncs.push_back(sysFunc); + cmptSysFuncs.latestSysFuncs.push_back(sysFunc); break; default: assert(false); @@ -64,16 +74,17 @@ unordered_map Schedule::GenCmptSysFuncsMap() con } } for (const auto& type : sysFunc->singletonLocator.SingletonTypes()) { + auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second; switch (type.GetAccessMode()) { case AccessMode::LAST_FRAME: - rst[type].lastFrameSysFuncs.push_back(sysFunc); + cmptSysFuncs.lastFrameSysFuncs.push_back(sysFunc); break; case AccessMode::WRITE: - rst[type].writeSysFuncs.push_back(sysFunc); + cmptSysFuncs.writeSysFuncs.push_back(sysFunc); break; case AccessMode::LATEST: - rst[type].latestSysFuncs.push_back(sysFunc); + cmptSysFuncs.latestSysFuncs.push_back(sysFunc); break; default: assert(false); @@ -81,16 +92,17 @@ unordered_map Schedule::GenCmptSysFuncsMap() con } } for (const auto& type : sysFunc->randomAccessor.types) { + auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second; switch (type.GetAccessMode()) { case AccessMode::LAST_FRAME: - rst[type].lastFrameSysFuncs.push_back(sysFunc); + cmptSysFuncs.lastFrameSysFuncs.push_back(sysFunc); break; case AccessMode::WRITE: - rst[type].writeSysFuncs.push_back(sysFunc); + cmptSysFuncs.writeSysFuncs.push_back(sysFunc); break; case AccessMode::LATEST: - rst[type].latestSysFuncs.push_back(sysFunc); + cmptSysFuncs.latestSysFuncs.push_back(sysFunc); break; default: assert(false); @@ -101,7 +113,7 @@ unordered_map Schedule::GenCmptSysFuncsMap() con if (sysFunc->GetMode() == SystemFunc::Mode::Chunk) { const auto& filter = sysFunc->entityQuery.filter; for (const auto& type : filter.all) { - auto& cmptSysFuncs = rst[type]; + auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second; switch (type.GetAccessMode()) { case AccessMode::LAST_FRAME: @@ -120,7 +132,7 @@ unordered_map Schedule::GenCmptSysFuncsMap() con } for (const auto& type : filter.any) { - auto& cmptSysFuncs = rst[type]; + auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second; switch (type.GetAccessMode()) { case AccessMode::LAST_FRAME: @@ -142,7 +154,7 @@ unordered_map Schedule::GenCmptSysFuncsMap() con return rst; } -SysFuncGraph Schedule::GenSysFuncGraph() const { +SysFuncGraph* Schedule::GenSysFuncGraph() const { // [change func Filter] for (const auto& [hashcode, change] : sysFilterChange) { auto target = sysFuncs.find(hashcode); @@ -157,14 +169,14 @@ SysFuncGraph Schedule::GenSysFuncGraph() const { func->entityQuery.filter.none.erase(type); } - auto cmptSysFuncsMap = GenCmptSysFuncsMap(); + CmptSysFuncsMap* cmptSysFuncsMap = GenCmptSysFuncsMap(); // use frame rsrc, no need to release // [gen graph] - SysFuncGraph graph; + SysFuncGraph* graph = CreateFrameObject(&frame_rsrc); // [gen graph] - vertex for (const auto& [hashcode, sysFunc] : sysFuncs) - graph.AddVertex(sysFunc); + graph->AddVertex(sysFunc); // [gen graph] - edge - order for (const auto& [x, y] : sysFuncOrder) { @@ -177,22 +189,22 @@ SysFuncGraph Schedule::GenSysFuncGraph() const { auto* sysFunc_x = target_x->second; auto* sysFunc_y = target_y->second; - graph.AddEdge(sysFunc_x, sysFunc_y); + graph->AddEdge(sysFunc_x, sysFunc_y); } // [gen graph] - edge - last frame -> write -> latest - for (const auto& [type, cmptSysFuncs] : cmptSysFuncsMap) { + for (const auto& [type, cmptSysFuncs] : *cmptSysFuncsMap) { if (cmptSysFuncs.writeSysFuncs.empty()) continue; - auto [success, sorted_wirtes] = graph.SubGraph(cmptSysFuncs.writeSysFuncs).Toposort(); + auto [success, sorted_wirtes] = graph->SubGraph({ cmptSysFuncs.writeSysFuncs.data(), cmptSysFuncs.writeSysFuncs.size() }).Toposort(); assert(success); for (auto* sys : cmptSysFuncs.lastFrameSysFuncs) - graph.AddEdge(sys, sorted_wirtes.front()); + graph->AddEdge(sys, sorted_wirtes.front()); for (auto* sys : cmptSysFuncs.latestSysFuncs) - graph.AddEdge(sorted_wirtes.back(), sys); + graph->AddEdge(sorted_wirtes.back(), sys); for (std::size_t i = 0; i < sorted_wirtes.size() - 1; i++) - graph.AddEdge(sorted_wirtes[i], sorted_wirtes[i + 1]); + graph->AddEdge(sorted_wirtes[i], sorted_wirtes[i + 1]); } return graph; diff --git a/src/core/SysFuncGraph.cpp b/src/core/SysFuncGraph.cpp index 944c576..5399b7c 100644 --- a/src/core/SysFuncGraph.cpp +++ b/src/core/SysFuncGraph.cpp @@ -13,7 +13,7 @@ bool SysFuncGraph::HaveVertex(SystemFunc* x) const { return adjList.find(x) != adjList.end(); } -bool SysFuncGraph::HaveVertices(const std::vector& vertices) const { +bool SysFuncGraph::HaveVertices(std::span vertices) const { for (auto v : vertices) { if (!HaveVertex(v)) return false; @@ -58,7 +58,7 @@ bool SysFuncGraph::HavePath(SystemFunc* x, SystemFunc* y) const { void SysFuncGraph::AddVertex(SystemFunc* x) { if (HaveVertex(x)) return; - adjList.emplace(x, unordered_set{}); + adjList.emplace(x, std::pmr::unordered_set(std::pmr::polymorphic_allocator{adjList.get_allocator().resource()})); } void SysFuncGraph::AddEdge(SystemFunc* x, SystemFunc* y) { @@ -68,9 +68,9 @@ void SysFuncGraph::AddEdge(SystemFunc* x, SystemFunc* y) { adjList[x].insert(y); } -SysFuncGraph SysFuncGraph::SubGraph(const std::vector& vertices) const { +SysFuncGraph SysFuncGraph::SubGraph(std::span vertices) const { assert(HaveVertices(vertices)); - SysFuncGraph subgraph; + SysFuncGraph subgraph{ adjList.get_allocator().resource() }; for (auto* v : vertices) subgraph.AddVertex(v); @@ -86,7 +86,7 @@ SysFuncGraph SysFuncGraph::SubGraph(const std::vector& vertices) co return subgraph; } -tuple> SysFuncGraph::Toposort() const { +tuple> SysFuncGraph::Toposort() const { unordered_map in_degree_map; for (const auto& [parent, children] : adjList) @@ -96,9 +96,10 @@ tuple> SysFuncGraph::Toposort() const { for (const auto& child : children) in_degree_map[child] += 1; } + std::pmr::polymorphic_allocator alloc{ adjList.get_allocator().resource() }; - stack zero_in_degree_vertices; - vector sorted_vertices; + stack> zero_in_degree_vertices; + std::pmr::vector sorted_vertices(alloc); for (const auto& [v, d] : in_degree_map) { if (d == 0) @@ -121,7 +122,7 @@ tuple> SysFuncGraph::Toposort() const { } if (!in_degree_map.empty()) - return { false, vector{} }; + return { false, std::pmr::vector(alloc) }; return { true, sorted_vertices }; } diff --git a/src/core/SysFuncGraph.h b/src/core/SysFuncGraph.h index ab11297..6a48c96 100644 --- a/src/core/SysFuncGraph.h +++ b/src/core/SysFuncGraph.h @@ -8,23 +8,25 @@ namespace Ubpa::UECS { class SystemFunc; class SysFuncGraph { public: - using AdjList = std::unordered_map>; + using AdjList = std::pmr::unordered_map>; + + SysFuncGraph(std::pmr::memory_resource* rsrc) : adjList{ AdjList::allocator_type{rsrc} } {} void AddVertex(SystemFunc* x); void AddEdge(SystemFunc* x, SystemFunc* y); bool HaveVertex(SystemFunc* x) const; - bool HaveVertices(const std::vector& vertices) const; + bool HaveVertices(std::span vertices) const; bool HaveEdge(SystemFunc* x, SystemFunc* y) const; bool HavePath(SystemFunc* x, SystemFunc* y) const; - SysFuncGraph SubGraph(const std::vector& vertices) const; - std::tuple> Toposort() const; + SysFuncGraph SubGraph(std::span vertices) const; + std::tuple> Toposort() const; bool IsDAG() const; const AdjList& GetAdjList() const noexcept { return adjList; } private: - std::unordered_map> adjList; + std::pmr::unordered_map> adjList; }; } diff --git a/src/core/SystemFunc.cpp b/src/core/SystemFunc.cpp index 2e4b123..aeb2fc9 100644 --- a/src/core/SystemFunc.cpp +++ b/src/core/SystemFunc.cpp @@ -1,4 +1,4 @@ -#include +#include using namespace Ubpa::UECS; diff --git a/src/core/World.cpp b/src/core/World.cpp index 45be48d..39167a8 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -52,22 +52,23 @@ void World::Update() { } schedule.commandBuffer.clear(); - const auto graph = schedule.GenSysFuncGraph(); + const auto* graph = schedule.GenSysFuncGraph(); // no need to delete - unordered_map table; + auto* table = schedule.CreateFrameObject> + (std::pmr::unordered_map::allocator_type{ schedule.GetFrameMonotonicResource() }); - for (const auto& [func, adjVs] : graph.GetAdjList()) { + for (const auto& [func, adjVs] : graph->GetAdjList()) { auto* job_buffer = jobRsrc->allocate(sizeof(Job), alignof(Job)); - auto* job = new(job_buffer)Job{ func->Name() }; + auto* job = new(job_buffer)Job{ std::string{func->Name()} }; jobs.push_back(job); entityMngr.AutoGen(this, job, func); - table.emplace(func, jobGraph.composed_of(*job)); + table->emplace(func, jobGraph.composed_of(*job)); } - for (const auto& [v, adjVs] : graph.GetAdjList()) { - auto vJob = table.at(v); + for (const auto& [v, adjVs] : graph->GetAdjList()) { + auto vJob = table->at(v); for (auto* adjV : adjVs) - vJob.precede(table.at(adjV)); + vJob.precede(table->at(adjV)); } executor.run(jobGraph).wait(); @@ -211,7 +212,7 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { } for (const auto& [hash, sysFunc] : schedule.sysFuncs) { - auto sysIdx = registry.RegisterNode(sysFunc->Name()); + auto sysIdx = registry.RegisterNode(std::string{ sysFunc->Name() }); sysFuncHashcode2idx.emplace(hash, sysIdx); subgraph_sys.AddNode(sysIdx);