Skip to content

Commit 1fcd535

Browse files
Merge pull request #806 from vsg-dev/AllocatorMapBlocks
Adopted std::map<> to vsg::Allocator for speeding up deletion
2 parents f02eba6 + e7c7c82 commit 1fcd535

2 files changed

Lines changed: 48 additions & 13 deletions

File tree

include/vsg/core/Allocator.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,15 @@ namespace vsg
9393
Allocator* parent = nullptr;
9494
std::string name;
9595
size_t blockSize = 0;
96-
std::list<std::unique_ptr<MemoryBlock>> memoryBlocks;
96+
std::map<void*, std::unique_ptr<MemoryBlock>> memoryBlocks;
97+
MemoryBlock* latestMemoryBlock = nullptr;
9798

9899
MemoryBlocks(Allocator* in_parent, const std::string& in_name, size_t in_blockSize);
99100
virtual ~MemoryBlocks();
100101

101102
void* allocate(std::size_t size);
102103
bool deallocate(void* ptr, std::size_t size);
104+
103105
size_t deleteEmptyMemoryBlocks();
104106
size_t totalAvailableSize() const;
105107
size_t totalReservedSize() const;
@@ -114,6 +116,9 @@ namespace vsg
114116

115117
mutable std::mutex mutex;
116118

119+
double allocationTime = 0.0;
120+
double deallocationTime = 0.0;
121+
117122
protected:
118123
// if you are assigning a custom allocator you must retain the old allocator to manage the memory it allocated and needs to delete
119124
std::unique_ptr<Allocator> nestedAllocator;
@@ -135,7 +140,7 @@ namespace vsg
135140

136141
allocator_affinity_nodes() = default;
137142
template<class U>
138-
constexpr allocator_affinity_nodes(const allocator_affinity_nodes<U>&) noexcept {}
143+
explicit constexpr allocator_affinity_nodes(const allocator_affinity_nodes<U>&) noexcept {}
139144

140145
value_type* allocate(std::size_t n)
141146
{

src/vsg/core/Allocator.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void Allocator::report(std::ostream& out) const
8080
if (memoryBlocks)
8181
{
8282
out << memoryBlocks->name << " " << memoryBlocks->memoryBlocks.size() << " blocks";
83-
for (const auto& memoryBlock : memoryBlocks->memoryBlocks)
83+
for (const auto& [ptr, memoryBlock] : memoryBlocks->memoryBlocks)
8484
{
8585
const auto& memorySlots = memoryBlock->memorySlots;
8686
out << " [used = " << memorySlots.totalReservedSize() << ", avail = " << memorySlots.maximumAvailableSpace() << "]";
@@ -272,7 +272,7 @@ void Allocator::setMemoryTracking(int mt)
272272
{
273273
if (amb)
274274
{
275-
for (auto& mb : amb->memoryBlocks)
275+
for (auto& [ptr, mb] : amb->memoryBlocks)
276276
{
277277
mb->memorySlots.memoryTracking = mt;
278278
}
@@ -371,20 +371,31 @@ Allocator::MemoryBlocks::~MemoryBlocks()
371371

372372
void* Allocator::MemoryBlocks::allocate(std::size_t size)
373373
{
374+
if (latestMemoryBlock)
375+
{
376+
auto ptr = latestMemoryBlock->allocate(size);
377+
if (ptr) return ptr;
378+
}
379+
374380
// search existing blocks from last to first for space for the required memory allocation.
375381
for (auto itr = memoryBlocks.rbegin(); itr != memoryBlocks.rend(); ++itr)
376382
{
377-
auto& block = *itr;
378-
auto ptr = block->allocate(size);
379-
if (ptr) return ptr;
383+
auto& block = itr->second;
384+
if (block.get() != latestMemoryBlock)
385+
{
386+
auto ptr = block->allocate(size);
387+
if (ptr) return ptr;
388+
}
380389
}
381390

382391
size_t new_blockSize = std::max(size, blockSize);
383392

384393
std::unique_ptr<MemoryBlock> block(new MemoryBlock(new_blockSize, parent->memoryTracking, parent->memoryBlocksAllocatorType));
394+
latestMemoryBlock = block.get();
395+
385396
auto ptr = block->allocate(size);
386397

387-
memoryBlocks.push_back(std::move(block));
398+
memoryBlocks[block->memory] = std::move(block);
388399

389400
if (parent->memoryTracking & MEMORY_TRACKING_REPORT_ACTIONS)
390401
{
@@ -396,8 +407,26 @@ void* Allocator::MemoryBlocks::allocate(std::size_t size)
396407

397408
bool Allocator::MemoryBlocks::deallocate(void* ptr, std::size_t size)
398409
{
399-
for (auto& block : memoryBlocks)
410+
if (memoryBlocks.empty()) return false;
411+
412+
auto itr = memoryBlocks.upper_bound(ptr);
413+
if (itr != memoryBlocks.end())
414+
{
415+
if (itr != memoryBlocks.begin())
416+
{
417+
--itr;
418+
auto& block = itr->second;
419+
if (block->deallocate(ptr, size)) return true;
420+
}
421+
else
422+
{
423+
auto& block = itr->second;
424+
if (block->deallocate(ptr, size)) return true;
425+
}
426+
}
427+
else
400428
{
429+
auto& block = memoryBlocks.rbegin()->second;
401430
if (block->deallocate(ptr, size)) return true;
402431
}
403432

@@ -419,13 +448,14 @@ size_t Allocator::MemoryBlocks::deleteEmptyMemoryBlocks()
419448
auto itr = memoryBlocks.begin();
420449
while (itr != memoryBlocks.end())
421450
{
422-
auto& block = *itr;
451+
auto& block = itr->second;
423452
if (block->memorySlots.empty())
424453
{
425454
if (parent->memoryTracking & MEMORY_TRACKING_REPORT_ACTIONS)
426455
{
427456
info(" MemoryBlocks:deleteEmptyMemoryBlocks() MemoryBlocks.name = ", name, ", removing MemoryBlock", block.get());
428457
}
458+
if (block.get() == latestMemoryBlock) latestMemoryBlock = nullptr;
429459
memoryDeleted += block->memorySlots.totalMemorySize();
430460
itr = memoryBlocks.erase(itr);
431461
}
@@ -440,7 +470,7 @@ size_t Allocator::MemoryBlocks::deleteEmptyMemoryBlocks()
440470
size_t Allocator::MemoryBlocks::totalAvailableSize() const
441471
{
442472
size_t size = 0;
443-
for (auto& block : memoryBlocks)
473+
for (auto& [ptr, block] : memoryBlocks)
444474
{
445475
size += block->memorySlots.totalAvailableSize();
446476
}
@@ -450,7 +480,7 @@ size_t Allocator::MemoryBlocks::totalAvailableSize() const
450480
size_t Allocator::MemoryBlocks::totalReservedSize() const
451481
{
452482
size_t size = 0;
453-
for (auto& block : memoryBlocks)
483+
for (auto& [ptr, block] : memoryBlocks)
454484
{
455485
size += block->memorySlots.totalReservedSize();
456486
}
@@ -460,7 +490,7 @@ size_t Allocator::MemoryBlocks::totalReservedSize() const
460490
size_t Allocator::MemoryBlocks::totalMemorySize() const
461491
{
462492
size_t size = 0;
463-
for (auto& block : memoryBlocks)
493+
for (auto& [ptr, block] : memoryBlocks)
464494
{
465495
size += block->memorySlots.totalMemorySize();
466496
}

0 commit comments

Comments
 (0)