Skip to content

Commit

Permalink
Merge pull request #806 from vsg-dev/AllocatorMapBlocks
Browse files Browse the repository at this point in the history
Adopted std::map<> to vsg::Allocator for speeding up deletion
  • Loading branch information
robertosfield authored May 10, 2023
2 parents f02eba6 + e7c7c82 commit 1fcd535
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 13 deletions.
9 changes: 7 additions & 2 deletions include/vsg/core/Allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ namespace vsg
Allocator* parent = nullptr;
std::string name;
size_t blockSize = 0;
std::list<std::unique_ptr<MemoryBlock>> memoryBlocks;
std::map<void*, std::unique_ptr<MemoryBlock>> 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;
Expand All @@ -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<Allocator> nestedAllocator;
Expand All @@ -135,7 +140,7 @@ namespace vsg

allocator_affinity_nodes() = default;
template<class U>
constexpr allocator_affinity_nodes(const allocator_affinity_nodes<U>&) noexcept {}
explicit constexpr allocator_affinity_nodes(const allocator_affinity_nodes<U>&) noexcept {}

value_type* allocate(std::size_t n)
{
Expand Down
52 changes: 41 additions & 11 deletions src/vsg/core/Allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() << "]";
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<MemoryBlock> 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)
{
Expand All @@ -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;
}

Expand All @@ -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);
}
Expand All @@ -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();
}
Expand All @@ -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();
}
Expand All @@ -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();
}
Expand Down

0 comments on commit 1fcd535

Please sign in to comment.