Skip to content

Commit 2987022

Browse files
authored
Merge pull request #1096 from redboltz/Arenoros-zone/optimization_size/delayed_malloc
Arenoros zone/optimization size/delayed malloc
2 parents 37fcaa1 + 34f531e commit 2987022

File tree

8 files changed

+400
-444
lines changed

8 files changed

+400
-444
lines changed

erb/v1/cpp03_zone.hpp.erb

Lines changed: 122 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -29,121 +29,101 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
2929

3030
class zone {
3131
struct finalizer {
32-
finalizer(void (*func)(void*), void* data):m_func(func), m_data(data) {}
32+
finalizer(void (*func)(void*), void* data, finalizer* next): m_func(func), m_data(data), m_next(next) {}
3333
void operator()() { m_func(m_data); }
3434
void (*m_func)(void*);
3535
void* m_data;
36+
finalizer* m_next;
3637
};
38+
3739
struct finalizer_array {
38-
finalizer_array():m_tail(MSGPACK_NULLPTR), m_end(MSGPACK_NULLPTR), m_array(MSGPACK_NULLPTR) {}
39-
void call() {
40-
finalizer* fin = m_tail;
41-
for(; fin != m_array; --fin) (*(fin-1))();
42-
}
40+
finalizer_array(): m_head(MSGPACK_NULLPTR) {}
41+
4342
~finalizer_array() {
44-
call();
45-
::free(m_array);
46-
}
47-
void clear() {
48-
call();
49-
m_tail = m_array;
43+
clear();
5044
}
51-
void push(void (*func)(void* data), void* data)
52-
{
53-
finalizer* fin = m_tail;
5445

55-
if(fin == m_end) {
56-
push_expand(func, data);
57-
return;
46+
void clear() {
47+
finalizer* fin = m_head;
48+
finalizer* tmp = MSGPACK_NULLPTR;
49+
while(fin) {
50+
(*fin)();
51+
tmp = fin;
52+
fin = fin->m_next;
53+
delete tmp;
5854
}
55+
m_head = MSGPACK_NULLPTR;
56+
}
5957

60-
fin->m_func = func;
61-
fin->m_data = data;
62-
63-
++m_tail;
58+
void push(void (*func)(void* data), void* data) {
59+
m_head = new finalizer(func, data, m_head);
6460
}
65-
void push_expand(void (*func)(void*), void* data) {
66-
const size_t nused = static_cast<size_t>(m_end - m_array);
67-
size_t nnext;
68-
if(nused == 0) {
69-
nnext = (sizeof(finalizer) < 72/2) ?
70-
72 / sizeof(finalizer) : 8;
71-
} else {
72-
nnext = nused * 2;
73-
}
74-
finalizer* tmp =
75-
static_cast<finalizer*>(::realloc(m_array, sizeof(finalizer) * nnext));
76-
if(!tmp) {
77-
throw std::bad_alloc();
78-
}
79-
m_array = tmp;
80-
m_end = tmp + nnext;
81-
m_tail = tmp + nused;
82-
new (m_tail) finalizer(func, data);
8361

84-
++m_tail;
62+
void pop() {
63+
finalizer* n = m_head->m_next;
64+
delete m_head;
65+
m_head = n;
8566
}
86-
finalizer* m_tail;
87-
finalizer* m_end;
88-
finalizer* m_array;
67+
68+
finalizer* m_head;
69+
private:
70+
finalizer_array(const finalizer_array&);
71+
finalizer_array& operator=(const finalizer_array&);
8972
};
73+
9074
struct chunk {
9175
chunk* m_next;
9276
};
93-
struct chunk_list {
94-
chunk_list(size_t chunk_size)
95-
{
96-
chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + chunk_size));
97-
if(!c) {
98-
throw std::bad_alloc();
99-
}
10077

101-
m_head = c;
102-
m_free = chunk_size;
103-
m_ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
104-
c->m_next = MSGPACK_NULLPTR;
105-
}
106-
~chunk_list()
107-
{
78+
struct chunk_list {
79+
chunk_list(size_t chunk_size, char* ptr): m_free(chunk_size), m_ptr(ptr), m_head(MSGPACK_NULLPTR) {}
80+
~chunk_list() {
10881
chunk* c = m_head;
10982
while(c) {
11083
chunk* n = c->m_next;
11184
::free(c);
11285
c = n;
11386
}
87+
m_head = MSGPACK_NULLPTR;
11488
}
115-
void clear(size_t chunk_size)
116-
{
89+
90+
void clear(size_t chunk_size, char* ptr) {
11791
chunk* c = m_head;
118-
while(true) {
92+
while(c) {
11993
chunk* n = c->m_next;
120-
if(n) {
121-
::free(c);
122-
c = n;
123-
} else {
124-
m_head = c;
125-
break;
126-
}
94+
::free(c);
95+
c = n;
12796
}
128-
m_head->m_next = MSGPACK_NULLPTR;
97+
m_head = MSGPACK_NULLPTR;
12998
m_free = chunk_size;
130-
m_ptr = reinterpret_cast<char*>(m_head) + sizeof(chunk);
99+
m_ptr = ptr;
131100
}
101+
132102
size_t m_free;
133103
char* m_ptr;
134104
chunk* m_head;
105+
106+
private:
107+
chunk_list(const chunk_list&);
108+
chunk_list& operator=(const chunk_list&);
135109
};
110+
136111
size_t m_chunk_size;
137-
chunk_list m_chunk_list;
112+
chunk_list* m_chunk_list;
138113
finalizer_array m_finalizer_array;
139114

140115
public:
141116
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
117+
~zone();
142118

143-
public:
144119
void* allocate_align(size_t size, size_t align = MSGPACK_ZONE_ALIGN);
120+
145121
void* allocate_no_align(size_t size);
146122

123+
bool allocated() {
124+
return m_chunk_list != MSGPACK_NULLPTR;
125+
}
126+
147127
void push_finalizer(void (*func)(void*), void* data);
148128

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

154134
void swap(zone& o);
155-
static void* operator new(std::size_t size)
156-
{
135+
136+
static void* operator new(std::size_t size) {
157137
void* p = ::malloc(size);
158138
if (!p) throw std::bad_alloc();
159139
return p;
160140
}
161-
static void operator delete(void *p) /* throw() */
162-
{
141+
142+
static void operator delete(void *p) /* throw() */ {
163143
::free(p);
164144
}
165-
static void* operator new(std::size_t size, void* place) /* throw() */
166-
{
167-
return ::operator new(size, place);
168-
}
169-
static void operator delete(void* p, void* place) /* throw() */
170-
{
171-
::operator delete(p, place);
145+
146+
static void* operator new(std::size_t /*size*/, void* mem) /* throw() */ {
147+
return mem;
172148
}
149+
150+
static void operator delete(void * /*p*/, void* /*mem*/) /* throw() */ {}
151+
173152
/// @cond
174153
<%0.upto(GENERATION_LIMIT) {|i|%>
175154
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
@@ -188,56 +167,72 @@ private:
188167

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

170+
chunk_list& get_chank_lst();
171+
191172
char* allocate_expand(size_t size);
192173
private:
193174
zone(const zone&);
194175
zone& operator=(const zone&);
195176
};
196177

197-
inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(m_chunk_size)
198-
{
178+
inline zone::zone(size_t chunk_size):m_chunk_size(chunk_size), m_chunk_list(MSGPACK_NULLPTR) {}
179+
180+
inline zone::~zone() {
181+
m_finalizer_array.~finalizer_array();
182+
if(m_chunk_list) {
183+
m_chunk_list->~chunk_list();
184+
::free(m_chunk_list);
185+
m_chunk_list = MSGPACK_NULLPTR;
186+
}
199187
}
200188

201-
inline char* zone::get_aligned(char* ptr, size_t align)
202-
{
189+
inline char* zone::get_aligned(char* ptr, size_t align) {
203190
MSGPACK_ASSERT(align != 0 && (align & (align - 1)) == 0); // align must be 2^n (n >= 0)
204191
return
205192
reinterpret_cast<char*>(
206193
reinterpret_cast<uintptr_t>(ptr + (align - 1)) & ~static_cast<uintptr_t>(align - 1)
207194
);
208195
}
209196

210-
inline void* zone::allocate_align(size_t size, size_t align)
211-
{
212-
char* aligned = get_aligned(m_chunk_list.m_ptr, align);
213-
size_t adjusted_size = size + static_cast<size_t>(aligned - m_chunk_list.m_ptr);
214-
if (m_chunk_list.m_free < adjusted_size) {
197+
inline zone::chunk_list& zone::get_chank_lst() {
198+
if (!m_chunk_list) {
199+
void* ptr = ::malloc(sizeof(chunk_list) + m_chunk_size);
200+
if (!ptr)
201+
throw std::bad_alloc();
202+
m_chunk_list = new (ptr) chunk_list(m_chunk_size, reinterpret_cast<char*>(ptr) + sizeof(chunk_list));
203+
}
204+
return *m_chunk_list;
205+
}
206+
207+
inline void* zone::allocate_align(size_t size, size_t align) {
208+
chunk_list& chank_lst = get_chank_lst();
209+
char* aligned = get_aligned(chank_lst.m_ptr, align);
210+
size_t adjusted_size = size + static_cast<size_t>(aligned - chank_lst.m_ptr);
211+
if (chank_lst.m_free < adjusted_size) {
215212
size_t enough_size = size + align - 1;
216213
char* ptr = allocate_expand(enough_size);
217214
aligned = get_aligned(ptr, align);
218-
adjusted_size = size + static_cast<size_t>(aligned - m_chunk_list.m_ptr);
215+
adjusted_size = size + static_cast<size_t>(aligned - chank_lst.m_ptr);
219216
}
220-
m_chunk_list.m_free -= adjusted_size;
221-
m_chunk_list.m_ptr += adjusted_size;
217+
chank_lst.m_free -= adjusted_size;
218+
chank_lst.m_ptr += adjusted_size;
222219
return aligned;
223220
}
224221

225-
inline void* zone::allocate_no_align(size_t size)
226-
{
227-
char* ptr = m_chunk_list.m_ptr;
228-
if(m_chunk_list.m_free < size) {
222+
inline void* zone::allocate_no_align(size_t size) {
223+
chunk_list& chank_lst = get_chank_lst();
224+
char* ptr = chank_lst.m_ptr;
225+
if(chank_lst.m_free < size) {
229226
ptr = allocate_expand(size);
230227
}
231-
m_chunk_list.m_free -= size;
232-
m_chunk_list.m_ptr += size;
228+
chank_lst.m_free -= size;
229+
chank_lst.m_ptr += size;
233230

234231
return ptr;
235232
}
236233

237-
inline char* zone::allocate_expand(size_t size)
238-
{
239-
chunk_list* const cl = &m_chunk_list;
240-
234+
inline char* zone::allocate_expand(size_t size) {
235+
chunk_list& cl = get_chank_lst();
241236
size_t sz = m_chunk_size;
242237

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

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

257-
c->m_next = cl->m_head;
258-
cl->m_head = c;
259-
cl->m_free = sz;
260-
cl->m_ptr = ptr;
252+
c->m_next = cl.m_head;
253+
cl.m_head = c;
254+
cl.m_free = sz;
255+
cl.m_ptr = ptr;
261256

262257
return ptr;
263258
}
264259

265-
inline void zone::push_finalizer(void (*func)(void*), void* data)
266-
{
260+
inline void zone::push_finalizer(void (*func)(void*), void* data) {
267261
m_finalizer_array.push(func, data);
268262
}
269263

270264
template <typename T>
271-
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
272-
{
265+
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj) {
273266
m_finalizer_array.push(&zone::object_delete<T>, obj.release());
274267
}
275268

276-
inline void zone::clear()
277-
{
269+
inline void zone::clear() {
278270
m_finalizer_array.clear();
279-
m_chunk_list.clear(m_chunk_size);
271+
if (m_chunk_list) {
272+
m_chunk_list->clear(m_chunk_size, reinterpret_cast<char*>(m_chunk_list) + sizeof(chunk_list));
273+
}
280274
}
281275

282-
inline void zone::swap(zone& o)
283-
{
276+
inline void zone::swap(zone& o) {
284277
using std::swap;
285278
swap(m_chunk_size, o.m_chunk_size);
286279
swap(m_chunk_list, o.m_chunk_list);
287-
swap(m_finalizer_array, o.m_finalizer_array);
280+
swap(m_finalizer_array.m_head, o.m_finalizer_array.m_head);
288281
}
289282

290283
template <typename T>
291-
void zone::object_destruct(void* obj)
292-
{
293-
static_cast<T*>(obj)->~T();
284+
void zone::object_delete(void* obj) {
285+
delete static_cast<T*>(obj);
294286
}
295287

296288
template <typename T>
297-
void zone::object_delete(void* obj)
298-
{
299-
delete static_cast<T*>(obj);
289+
void zone::object_destruct(void* obj) {
290+
static_cast<T*>(obj)->~T();
300291
}
301292

302-
inline void zone::undo_allocate(size_t size)
303-
{
304-
m_chunk_list.m_ptr -= size;
305-
m_chunk_list.m_free += size;
293+
inline void zone::undo_allocate(size_t size) {
294+
chunk_list& cl = get_chank_lst();
295+
cl.m_ptr -= size;
296+
cl.m_free += size;
306297
}
307298

308-
inline std::size_t aligned_size(
309-
std::size_t size,
310-
std::size_t align) {
299+
inline std::size_t aligned_size(std::size_t size, std::size_t align) {
311300
return (size + align - 1) / align * align;
312301
}
313302

@@ -326,7 +315,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
326315
try {
327316
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
328317
} catch (...) {
329-
--m_finalizer_array.m_tail;
318+
m_finalizer_array.pop();
330319
undo_allocate(sizeof(T));
331320
throw;
332321
}

0 commit comments

Comments
 (0)