Skip to content

Commit

Permalink
Merge pull request #1096 from redboltz/Arenoros-zone/optimization_siz…
Browse files Browse the repository at this point in the history
…e/delayed_malloc

Arenoros zone/optimization size/delayed malloc
  • Loading branch information
redboltz authored Oct 3, 2023
2 parents 37fcaa1 + 34f531e commit 2987022
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 444 deletions.
255 changes: 122 additions & 133 deletions erb/v1/cpp03_zone.hpp.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,121 +29,101 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {

class zone {
struct finalizer {
finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {}
finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next) {}
void operator()() { m_func(m_data); }
void (*m_func)(void*);
void* m_data;
finalizer* m_next;
};

struct finalizer_array {
finalizer_array():m_tail(MSGPACK_NULLPTR), m_end(MSGPACK_NULLPTR), m_array(MSGPACK_NULLPTR) {}
void call() {
finalizer* fin = m_tail;
for(; fin != m_array; --fin) (*(fin-1))();
}
finalizer_array(): m_head(MSGPACK_NULLPTR) {}

~finalizer_array() {
call();
::free(m_array);
}
void clear() {
call();
m_tail = m_array;
clear();
}
void push(void (*func)(void* data), void* data)
{
finalizer* fin = m_tail;

if(fin == m_end) {
push_expand(func, data);
return;
void clear() {
finalizer* fin = m_head;
finalizer* tmp = MSGPACK_NULLPTR;
while(fin) {
(*fin)();
tmp = fin;
fin = fin->m_next;
delete tmp;
}
m_head = MSGPACK_NULLPTR;
}

fin->m_func = func;
fin->m_data = data;

++m_tail;
void push(void (*func)(void* data), void* data) {
m_head = new finalizer(func, data, m_head);
}
void push_expand(void (*func)(void*), void* data) {
const size_t nused = static_cast<size_t>(m_end - m_array);
size_t nnext;
if(nused == 0) {
nnext = (sizeof(finalizer) < 72/2) ?
72 / sizeof(finalizer) : 8;
} else {
nnext = nused * 2;
}
finalizer* tmp =
static_cast<finalizer*>(::realloc(m_array, sizeof(finalizer) * nnext));
if(!tmp) {
throw std::bad_alloc();
}
m_array = tmp;
m_end = tmp + nnext;
m_tail = tmp + nused;
new (m_tail) finalizer(func, data);

++m_tail;
void pop() {
finalizer* n = m_head->m_next;
delete m_head;
m_head = n;
}
finalizer* m_tail;
finalizer* m_end;
finalizer* m_array;

finalizer* m_head;
private:
finalizer_array(const finalizer_array&);
finalizer_array& operator=(const finalizer_array&);
};

struct chunk {
chunk* m_next;
};
struct chunk_list {
chunk_list(size_t chunk_size)
{
chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + chunk_size));
if(!c) {
throw std::bad_alloc();
}

m_head = c;
m_free = chunk_size;
m_ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
c->m_next = MSGPACK_NULLPTR;
}
~chunk_list()
{
struct chunk_list {
chunk_list(size_t chunk_size, char* ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {}
~chunk_list() {
chunk* c = m_head;
while(c) {
chunk* n = c->m_next;
::free(c);
c = n;
}
m_head = MSGPACK_NULLPTR;
}
void clear(size_t chunk_size)
{

void clear(size_t chunk_size, char* ptr) {
chunk* c = m_head;
while(true) {
while(c) {
chunk* n = c->m_next;
if(n) {
::free(c);
c = n;
} else {
m_head = c;
break;
}
::free(c);
c = n;
}
m_head->m_next = MSGPACK_NULLPTR;
m_head = MSGPACK_NULLPTR;
m_free = chunk_size;
m_ptr = reinterpret_cast<char*>(m_head) + sizeof(chunk);
m_ptr = ptr;
}

size_t m_free;
char* m_ptr;
chunk* m_head;

private:
chunk_list(const chunk_list&);
chunk_list& operator=(const chunk_list&);
};

size_t m_chunk_size;
chunk_list m_chunk_list;
chunk_list* m_chunk_list;
finalizer_array m_finalizer_array;

public:
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
~zone();

public:
void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN);

void* allocate_no_align(size_t size);

bool allocated() {
return m_chunk_list != MSGPACK_NULLPTR;
}

void push_finalizer(void (*func)(void*), void* data);

template <typename T>
Expand All @@ -152,24 +132,23 @@ public:
void clear();

void swap(zone& o);
static void* operator new(std::size_t size)
{

static void* operator new(std::size_t size) {
void* p = ::malloc(size);
if (!p) throw std::bad_alloc();
return p;
}
static void operator delete(void *p) /* throw() */
{

static void operator delete(void *p) /* throw() */ {
::free(p);
}
static void* operator new(std::size_t size, void* place) /* throw() */
{
return ::operator new(size, place);
}
static void operator delete(void* p, void* place) /* throw() */
{
::operator delete(p, place);

static void* operator new(std::size_t /*size*/, void* mem) /* throw() */ {
return mem;
}

static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {}

/// @cond
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
Expand All @@ -188,56 +167,72 @@ private:

static char* get_aligned(char* ptr, size_t align);

chunk_list& get_chank_lst();

char* allocate_expand(size_t size);
private:
zone(const zone&);
zone& operator=(const zone&);
};

inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
{
inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(MSGPACK_NULLPTR) {}

inline zone::~zone() {
m_finalizer_array.~finalizer_array();
if(m_chunk_list) {
m_chunk_list->~chunk_list();
::free(m_chunk_list);
m_chunk_list = MSGPACK_NULLPTR;
}
}

inline char* zone::get_aligned(char* ptr, size_t align)
{
inline char* zone::get_aligned(char* ptr, size_t align) {
MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n >= 0)
return
reinterpret_cast<char*>(
reinterpret_cast<uintptr_t>(ptr + (align - 1)) & ~static_cast<uintptr_t>(align - 1)
);
}

inline void* zone::allocate_align(size_t size, size_t align)
{
char* aligned = get_aligned(m_chunk_list.m_ptr, align);
size_t adjusted_size = size + static_cast<size_t>(aligned - m_chunk_list.m_ptr);
if (m_chunk_list.m_free < adjusted_size) {
inline zone::chunk_list& zone::get_chank_lst() {
if (!m_chunk_list) {
void* ptr = ::malloc(sizeof(chunk_list) + m_chunk_size);
if (!ptr)
throw std::bad_alloc();
m_chunk_list = new (ptr) chunk_list(m_chunk_size, reinterpret_cast<char*>(ptr) + sizeof(chunk_list));
}
return *m_chunk_list;
}

inline void* zone::allocate_align(size_t size, size_t align) {
chunk_list& chank_lst = get_chank_lst();
char* aligned = get_aligned(chank_lst.m_ptr, align);
size_t adjusted_size = size + static_cast<size_t>(aligned - chank_lst.m_ptr);
if (chank_lst.m_free < adjusted_size) {
size_t enough_size = size + align - 1;
char* ptr = allocate_expand(enough_size);
aligned = get_aligned(ptr, align);
adjusted_size = size + static_cast<size_t>(aligned - m_chunk_list.m_ptr);
adjusted_size = size + static_cast<size_t>(aligned - chank_lst.m_ptr);
}
m_chunk_list.m_free -= adjusted_size;
m_chunk_list.m_ptr += adjusted_size;
chank_lst.m_free -= adjusted_size;
chank_lst.m_ptr += adjusted_size;
return aligned;
}

inline void* zone::allocate_no_align(size_t size)
{
char* ptr = m_chunk_list.m_ptr;
if(m_chunk_list.m_free < size) {
inline void* zone::allocate_no_align(size_t size) {
chunk_list& chank_lst = get_chank_lst();
char* ptr = chank_lst.m_ptr;
if(chank_lst.m_free < size) {
ptr = allocate_expand(size);
}
m_chunk_list.m_free -= size;
m_chunk_list.m_ptr += size;
chank_lst.m_free -= size;
chank_lst.m_ptr += size;

return ptr;
}

inline char* zone::allocate_expand(size_t size)
{
chunk_list* const cl = &m_chunk_list;

inline char* zone::allocate_expand(size_t size) {
chunk_list& cl = get_chank_lst();
size_t sz = m_chunk_size;

while(sz < size) {
Expand All @@ -254,60 +249,54 @@ inline char* zone::allocate_expand(size_t size)

char* ptr = reinterpret_cast<char*>(c) + sizeof(chunk);

c->m_next = cl->m_head;
cl->m_head = c;
cl->m_free = sz;
cl->m_ptr = ptr;
c->m_next = cl.m_head;
cl.m_head = c;
cl.m_free = sz;
cl.m_ptr = ptr;

return ptr;
}

inline void zone::push_finalizer(void (*func)(void*), void* data)
{
inline void zone::push_finalizer(void (*func)(void*), void* data) {
m_finalizer_array.push(func, data);
}

template <typename T>
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
{
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj) {
m_finalizer_array.push(&zone::object_delete<T>, obj.release());
}

inline void zone::clear()
{
inline void zone::clear() {
m_finalizer_array.clear();
m_chunk_list.clear(m_chunk_size);
if (m_chunk_list) {
m_chunk_list->clear(m_chunk_size, reinterpret_cast<char*>(m_chunk_list) + sizeof(chunk_list));
}
}

inline void zone::swap(zone& o)
{
inline void zone::swap(zone& o) {
using std::swap;
swap(m_chunk_size, o.m_chunk_size);
swap(m_chunk_list, o.m_chunk_list);
swap(m_finalizer_array, o.m_finalizer_array);
swap(m_finalizer_array.m_head, o.m_finalizer_array.m_head);
}

template <typename T>
void zone::object_destruct(void* obj)
{
static_cast<T*>(obj)->~T();
void zone::object_delete(void* obj) {
delete static_cast<T*>(obj);
}

template <typename T>
void zone::object_delete(void* obj)
{
delete static_cast<T*>(obj);
void zone::object_destruct(void* obj) {
static_cast<T*>(obj)->~T();
}

inline void zone::undo_allocate(size_t size)
{
m_chunk_list.m_ptr -= size;
m_chunk_list.m_free += size;
inline void zone::undo_allocate(size_t size) {
chunk_list& cl = get_chank_lst();
cl.m_ptr -= size;
cl.m_free += size;
}

inline std::size_t aligned_size(
std::size_t size,
std::size_t align) {
inline std::size_t aligned_size(std::size_t size, std::size_t align) {
return (size + align - 1) / align * align;
}

Expand All @@ -326,7 +315,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
try {
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
} catch (...) {
--m_finalizer_array.m_tail;
m_finalizer_array.pop();
undo_allocate(sizeof(T));
throw;
}
Expand Down
Loading

0 comments on commit 2987022

Please sign in to comment.