From 9cb5372e23773884e7ced06b3bb0190b9e99dae6 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 9 May 2023 14:45:26 +0100 Subject: [PATCH 1/2] Adopted std::map<> for speedig up deletion --- include/vsg/core/Allocator.h | 7 ++++- src/vsg/core/Allocator.cpp | 52 ++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/include/vsg/core/Allocator.h b/include/vsg/core/Allocator.h index e502d1883..639e632d2 100644 --- a/include/vsg/core/Allocator.h +++ b/include/vsg/core/Allocator.h @@ -93,13 +93,15 @@ namespace vsg Allocator* parent = nullptr; std::string name; size_t blockSize = 0; - std::list> memoryBlocks; + std::map> memoryBlocks; + MemoryBlock* latestMemoryBlock = nullptr; MemoryBlocks(Allocator* in_parent, const std::string& in_name, size_t in_blockSize); virtual ~MemoryBlocks(); void* allocate(std::size_t size); bool deallocate(void* ptr, std::size_t size); + size_t deleteEmptyMemoryBlocks(); size_t totalAvailableSize() const; size_t totalReservedSize() const; @@ -114,6 +116,9 @@ namespace vsg mutable std::mutex mutex; + double allocationTime = 0.0; + double deallocationTime = 0.0; + protected: // if you are assigning a custom allocator you must retain the old allocator to manage the memory it allocated and needs to delete std::unique_ptr nestedAllocator; diff --git a/src/vsg/core/Allocator.cpp b/src/vsg/core/Allocator.cpp index f30c623fd..9b3a0a9da 100644 --- a/src/vsg/core/Allocator.cpp +++ b/src/vsg/core/Allocator.cpp @@ -80,7 +80,7 @@ void Allocator::report(std::ostream& out) const if (memoryBlocks) { out << memoryBlocks->name << " " << memoryBlocks->memoryBlocks.size() << " blocks"; - for (const auto& memoryBlock : memoryBlocks->memoryBlocks) + for (const auto& [ptr, memoryBlock] : memoryBlocks->memoryBlocks) { const auto& memorySlots = memoryBlock->memorySlots; out << " [used = " << memorySlots.totalReservedSize() << ", avail = " << memorySlots.maximumAvailableSpace() << "]"; @@ -272,7 +272,7 @@ void Allocator::setMemoryTracking(int mt) { if (amb) { - for (auto& mb : amb->memoryBlocks) + for (auto& [ptr, mb] : amb->memoryBlocks) { mb->memorySlots.memoryTracking = mt; } @@ -371,20 +371,31 @@ Allocator::MemoryBlocks::~MemoryBlocks() void* Allocator::MemoryBlocks::allocate(std::size_t size) { + if (latestMemoryBlock) + { + auto ptr = latestMemoryBlock->allocate(size); + if (ptr) return ptr; + } + // search existing blocks from last to first for space for the required memory allocation. for (auto itr = memoryBlocks.rbegin(); itr != memoryBlocks.rend(); ++itr) { - auto& block = *itr; - auto ptr = block->allocate(size); - if (ptr) return ptr; + auto& block = itr->second; + if (block.get() != latestMemoryBlock) + { + auto ptr = block->allocate(size); + if (ptr) return ptr; + } } size_t new_blockSize = std::max(size, blockSize); std::unique_ptr block(new MemoryBlock(new_blockSize, parent->memoryTracking, parent->memoryBlocksAllocatorType)); + latestMemoryBlock = block.get(); + auto ptr = block->allocate(size); - memoryBlocks.push_back(std::move(block)); + memoryBlocks[block->memory] = std::move(block); if (parent->memoryTracking & MEMORY_TRACKING_REPORT_ACTIONS) { @@ -396,8 +407,26 @@ void* Allocator::MemoryBlocks::allocate(std::size_t size) bool Allocator::MemoryBlocks::deallocate(void* ptr, std::size_t size) { - for (auto& block : memoryBlocks) + if (memoryBlocks.empty()) return false; + + auto itr = memoryBlocks.upper_bound(ptr); + if (itr != memoryBlocks.end()) + { + if (itr != memoryBlocks.begin()) + { + --itr; + auto& block = itr->second; + if (block->deallocate(ptr, size)) return true; + } + else + { + auto& block = itr->second; + if (block->deallocate(ptr, size)) return true; + } + } + else { + auto& block = memoryBlocks.rbegin()->second; if (block->deallocate(ptr, size)) return true; } @@ -419,13 +448,14 @@ size_t Allocator::MemoryBlocks::deleteEmptyMemoryBlocks() auto itr = memoryBlocks.begin(); while (itr != memoryBlocks.end()) { - auto& block = *itr; + auto& block = itr->second; if (block->memorySlots.empty()) { if (parent->memoryTracking & MEMORY_TRACKING_REPORT_ACTIONS) { info(" MemoryBlocks:deleteEmptyMemoryBlocks() MemoryBlocks.name = ", name, ", removing MemoryBlock", block.get()); } + if (block.get() == latestMemoryBlock) latestMemoryBlock = nullptr; memoryDeleted += block->memorySlots.totalMemorySize(); itr = memoryBlocks.erase(itr); } @@ -440,7 +470,7 @@ size_t Allocator::MemoryBlocks::deleteEmptyMemoryBlocks() size_t Allocator::MemoryBlocks::totalAvailableSize() const { size_t size = 0; - for (auto& block : memoryBlocks) + for (auto& [ptr, block] : memoryBlocks) { size += block->memorySlots.totalAvailableSize(); } @@ -450,7 +480,7 @@ size_t Allocator::MemoryBlocks::totalAvailableSize() const size_t Allocator::MemoryBlocks::totalReservedSize() const { size_t size = 0; - for (auto& block : memoryBlocks) + for (auto& [ptr, block] : memoryBlocks) { size += block->memorySlots.totalReservedSize(); } @@ -460,7 +490,7 @@ size_t Allocator::MemoryBlocks::totalReservedSize() const size_t Allocator::MemoryBlocks::totalMemorySize() const { size_t size = 0; - for (auto& block : memoryBlocks) + for (auto& [ptr, block] : memoryBlocks) { size += block->memorySlots.totalMemorySize(); } From e7c7c82014bec13632949b2d3da2be24c98ab7ae Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 10 May 2023 10:53:11 +0100 Subject: [PATCH 2/2] Fixed cppcheck reported issue --- include/vsg/core/Allocator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/vsg/core/Allocator.h b/include/vsg/core/Allocator.h index 639e632d2..376803838 100644 --- a/include/vsg/core/Allocator.h +++ b/include/vsg/core/Allocator.h @@ -140,7 +140,7 @@ namespace vsg allocator_affinity_nodes() = default; template - constexpr allocator_affinity_nodes(const allocator_affinity_nodes&) noexcept {} + explicit constexpr allocator_affinity_nodes(const allocator_affinity_nodes&) noexcept {} value_type* allocate(std::size_t n) {