35 #ifndef INCLUDE_NRT_CORE_MEMORY_DETAILS_ALLOCATIONHELPERS_H_
36 #define INCLUDE_NRT_CORE_MEMORY_DETAILS_ALLOCATIONHELPERS_H_
41 #include <nrt/Core/Memory/details/freelist.h>
47 namespace memorydetail
57 void set_allow_caching(
bool )
62 void show_stats(
int ,
const char* ,
63 const size_t block_size,
const size_t overhead)
const
68 void* allocate(
size_t nbytes, nrt::rutz::free_list_base** source = 0)
72 return ::operator
new(nbytes);
75 void deallocate(
void* space, nrt::rutz::free_list_base* source = 0)
78 ::operator
delete(space);
81 void release_free_mem()
88 template <
size_t cache_size>
91 nrt::rutz::free_list_base* cache[cache_size];
92 mutable size_t num_alloc[cache_size];
98 for (
size_t i = 0; i < cache_size; ++i)
101 this->num_alloc[i] = 0;
110 for(
size_t i=0; i<cache_size; ++i)
114 void set_debug(
bool )
119 void set_allow_caching(
bool on)
121 if (!on && this->allow_caching)
126 this->release_free_mem();
128 this->allow_caching = on;
131 void show_stats(
int verbosity,
const char* pfx,
132 const size_t block_size,
const size_t overhead)
const
135 size_t bytes_allocated = 0;
137 std::map<size_t, std::string> msgs;
139 for (
size_t i = 0; i < cache_size; ++i)
140 if (this->cache[i] != 0)
143 const size_t nb = (this->cache[i]->num_allocations()
144 * this->cache[i]->alloc_size());
146 const size_t extra = (this->cache[i]->num_allocations()
147 - this->num_alloc[i]);
149 this->num_alloc[i] = this->cache[i]->num_allocations();
151 bytes_allocated += nb;
158 "%10.4fMB in %zu allocations of %10.4fkB",
159 pfx ? pfx :
"", pfx ?
": " :
"",
160 i, cache_size, nb / (1024.0*1024.0),
161 this->cache[i]->num_allocations(),
162 this->cache[i]->alloc_size() / 1024.0);
166 if (this->cache[i]->alloc_size() - overhead >= block_size
167 || this->cache[i]->alloc_size() - overhead <= 1)
170 (
double(this->cache[i]->alloc_size() - overhead)
171 /
double(block_size)),
177 /
double(this->cache[i]->alloc_size() - overhead)),
184 msgs[this->cache[i]->alloc_size()] = msg;
187 for (std::map<size_t, std::string>::const_iterator
188 itr = msgs.begin(), stop = msgs.end();
194 nrt::sformat(
"%s%sfastcache_alloc<%zu>: %zu/%zu cache table "
195 "entries in use, %fMB total allocated",
196 pfx ? pfx :
"", pfx ?
": " :
"",
197 cache_size, nused, cache_size,
198 bytes_allocated / (1024.0*1024.0));
203 double(bytes_allocated) /
double(block_size));
211 void* allocate(
size_t nbytes, nrt::rutz::free_list_base** source)
213 if (this->allow_caching && source != 0)
214 for (
size_t i = 0; i < cache_size; ++i)
216 if (this->cache[i] != 0)
220 if (this->cache[i]->alloc_size() == nbytes)
222 *source = this->cache[i];
223 return this->cache[i]->allocate(nbytes);
231 this->cache[i] =
new nrt::rutz::free_list_base(nbytes);
232 *source = this->cache[i];
233 return this->cache[i]->allocate(nbytes);
238 return ::operator
new(nbytes);
243 void deallocate(
void* space, nrt::rutz::free_list_base* source)
247 source->deallocate(space);
248 if (!this->allow_caching)
249 source->release_free_nodes();
253 ::operator
delete(space);
257 void release_free_mem()
259 for (
size_t i = 0; i < cache_size; ++i)
260 if (this->cache[i] != 0)
261 this->cache[i]->release_free_nodes();
277 nrt::rutz::free_list_base* source;
279 unsigned long align()
const
281 return reinterpret_cast<unsigned long>(this->alloc_addr) % N;
284 unsigned long adjust()
const
286 return N-this->align();
289 void* user_addr()
const
292 static_cast<char*
>(this->alloc_addr)
297 unsigned long user_align()
const
299 return reinterpret_cast<unsigned long>(this->user_addr()) % N;
305 "user=[%p (align%zu=%lu)]",
306 this->alloc_addr, N, this->align(), this->user_addr(), N, this->user_align()));
311 static const int pad_size = int(N) - int(
sizeof(data_s));
312 static_assert(pad_size >= 0,
"Minimum alignment size is 16 bytes");
317 template <
class src_type,
size_t N>
322 bool do_debug_printing;
323 double nbytes_allocated;
325 size_t nbytes_current;
326 size_t nallocations_current;
330 static_assert(
sizeof(
alloc_info<N>) == N,
"Sizeof assumptions about alloc_info are wrong!");
335 do_debug_printing(
false),
336 nbytes_allocated(0.0),
339 nallocations_current(0)
344 void set_debug(
bool do_debug)
346 this->do_debug_printing = do_debug;
349 src_alloc.set_debug(do_debug);
352 void set_allow_caching(
bool on)
354 src_alloc.set_allow_caching(on);
357 void show_stats(
int verbosity,
const char* pfx,
358 const size_t block_size,
const size_t overhead)
const
361 "all-time: [%fMB in %zu allocations], "
362 "current: [%fMB in %zu allocations]",
366 double(this->nbytes_allocated)/(1024.0*1024.0), this->nallocations,
367 double(this->nbytes_current)/(1024.0*1024.0), this->nallocations_current));
370 src_alloc.show_stats(verbosity, pfx, block_size, overhead+2*N);
373 void* allocate(
size_t user_nbytes)
376 info.data.source = 0;
385 size_t alloc_nbytes = user_nbytes+2*N;
387 info.data.alloc_addr =
388 this->src_alloc.allocate(alloc_nbytes, &info.data.source);
408 void*
const user_addr = info.data.user_addr();
413 ++this->nallocations;
415 ++this->nallocations_current;
417 if (this->do_debug_printing)
420 this->show_stats(0, 0, 0, 0);
426 void deallocate(
void* user_addr)
432 --this->nallocations_current;
434 if (this->do_debug_printing)
437 this->show_stats(0, 0, 0, 0);
440 this->src_alloc.deallocate(info->data.alloc_addr, info->data.source);
443 void release_free_mem()
445 this->src_alloc.release_free_mem();
451 #endif // INCLUDE_NRT_CORE_MEMORY_DETAILS_ALLOCATIONHELPERS_H_