Introduce DefragAllocator

This commit is contained in:
Alexander A. Klimov 2023-08-29 15:30:57 +02:00
parent 7a21001d6d
commit 97eda30f86
3 changed files with 107 additions and 3 deletions

View File

@ -14,7 +14,7 @@ mkclass_target(sysloglogger.ti sysloglogger-ti.cpp sysloglogger-ti.hpp)
set(base_SOURCES
i2-base.hpp
allocator.cpp
allocator.cpp allocator.hpp
application.cpp application.hpp application-ti.hpp application-version.cpp application-environment.cpp
array.cpp array.hpp array-script.cpp
atomic.hpp

View File

@ -2,19 +2,99 @@
#ifndef _WIN32
#include "base/allocator.hpp"
#include <algorithm>
#include <boost/config.hpp>
#include <cstddef>
#include <dlfcn.h>
#include <sys/mman.h>
#include <unistd.h>
using namespace icinga;
struct DAPage
{
size_t TotalSize = sizeof(DAPage);
DAPage* Next = nullptr;
max_align_t* MemoryBegin = nullptr;
max_align_t* MemoryEnd = nullptr;
max_align_t Memory[1] = {};
};
static thread_local struct {
unsigned int InUse = 0;
DAPage* TopPage = nullptr;
} l_DefragAllocator;
extern "C" void* malloc(size_t bytes)
{
static const auto libcMalloc = (void*(*)(size_t))dlsym(RTLD_NEXT, "malloc");
static const size_t pageSize = std::max(128L * 1024L, sysconf(_SC_PAGESIZE));
if (BOOST_LIKELY(!l_DefragAllocator.InUse)) {
return libcMalloc(bytes);
}
if (BOOST_UNLIKELY(!bytes)) {
return nullptr;
}
auto chunks ((bytes + sizeof(max_align_t) - 1u) / sizeof(max_align_t));
if (BOOST_UNLIKELY(!l_DefragAllocator.TopPage || l_DefragAllocator.TopPage->MemoryEnd - l_DefragAllocator.TopPage->MemoryBegin < chunks)) {
auto total ((sizeof(DAPage) + sizeof(max_align_t) * (chunks - 1u) + pageSize - 1u) / pageSize * pageSize);
auto nextPage (mmap(nullptr, total, PROT_READ | PROT_WRITE, MAP_ANONYMOUS
#ifdef MAP_HASSEMAPHORE
| MAP_HASSEMAPHORE
#endif
| MAP_PRIVATE, -1, 0));
if (BOOST_UNLIKELY(nextPage == MAP_FAILED)) {
return nullptr;
}
auto p ((DAPage*)nextPage);
p->TotalSize = total;
p->Next = l_DefragAllocator.TopPage;
p->MemoryBegin = p->Memory;
p->MemoryEnd = p->MemoryBegin + chunks;
l_DefragAllocator.TopPage = p;
}
auto memory ((void*)l_DefragAllocator.TopPage->MemoryBegin);
l_DefragAllocator.TopPage->MemoryBegin += chunks;
return memory;
}
extern "C" void free(void* memory)
{
static const auto libcFree = (void(*)(void*))dlsym(RTLD_NEXT, "free");
if (BOOST_LIKELY(!l_DefragAllocator.InUse)) {
libcFree(memory);
}
}
DefragAllocator::DefragAllocator()
{
++l_DefragAllocator.InUse;
}
DefragAllocator::~DefragAllocator()
{
if (!--l_DefragAllocator.InUse) {
while (l_DefragAllocator.TopPage) {
auto next (l_DefragAllocator.TopPage->Next);
munmap(l_DefragAllocator.TopPage, l_DefragAllocator.TopPage->TotalSize);
l_DefragAllocator.TopPage = next;
}
}
}
#endif /* _WIN32 */

24
lib/base/allocator.hpp Normal file
View File

@ -0,0 +1,24 @@
/* Icinga 2 | (c) 2023 Icinga GmbH | GPLv2+ */
#pragma once
namespace icinga
{
/**
* TODO
*
* @ingroup base
*/
class DefragAllocator
{
public:
DefragAllocator();
DefragAllocator(const DefragAllocator&) = delete;
DefragAllocator(DefragAllocator&&) = delete;
DefragAllocator& operator=(const DefragAllocator&) = delete;
DefragAllocator& operator=(DefragAllocator&&) = delete;
~DefragAllocator();
};
}