8#include <unordered_map>
21bool allocator_destroyed =
false;
26#ifndef NO_MULTITHREADING
28std::mutex manual_slabs_mutex;
30template <
typename... Args>
inline void dbg_info(Args... args)
36 (void)(
sizeof...(args));
49 size_t circuit_size_hint_;
51#ifndef NO_MULTITHREADING
52 std::mutex memory_store_mutex;
57 SlabAllocator() =
default;
58 SlabAllocator(
const SlabAllocator& other) =
delete;
59 SlabAllocator(SlabAllocator&& other) =
delete;
60 SlabAllocator& operator=(
const SlabAllocator& other) =
delete;
61 SlabAllocator& operator=(SlabAllocator&& other) =
delete;
63 void init(
size_t circuit_size_hint);
67 size_t get_total_size();
70 void release(
void* ptr,
size_t size);
73SlabAllocator::~SlabAllocator()
75 allocator_destroyed =
true;
76 for (
auto& e : memory_store) {
77 for (
auto& p : e.second) {
83void SlabAllocator::init(
size_t circuit_size_hint)
85 if (circuit_size_hint <= circuit_size_hint_) {
89 circuit_size_hint_ = circuit_size_hint;
92 for (
auto& e : memory_store) {
93 for (
auto& p : e.second) {
99 dbg_info(
"slab allocator initing for size: ", circuit_size_hint);
101 if (circuit_size_hint == 0ULL) {
106 size_t overalloc = 512;
107 size_t base_size = circuit_size_hint + overalloc;
118 prealloc_num[base_size * 32] = 11;
119 prealloc_num[base_size * 32 * 2] = 1;
120 prealloc_num[base_size * 32 * 3] = 1;
121 prealloc_num[base_size * 32 * 4] = 1 +
128 prealloc_num[base_size * 32 * 8] = 1 +
131 for (
auto& e : prealloc_num) {
132 for (
size_t i = 0; i < e.second; ++i) {
134 memory_store[size].push_back(aligned_alloc(32, size));
135 dbg_info(
"Allocated memory slab of size: ", size,
" total: ", get_total_size());
142#ifndef NO_MULTITHREADING
146 auto it = memory_store.lower_bound(req_size);
149 if (it != memory_store.end() && it->first < req_size * 2) {
150 size_t size = it->first;
151 auto* ptr = it->second.back();
152 it->second.pop_back();
154 if (it->second.empty()) {
155 memory_store.erase(it);
158 if (req_size >= circuit_size_hint_ && size > req_size + req_size / 10) {
159 dbg_info(
"WARNING: Using memory slab of size: ",
166 dbg_info(
"Reusing memory slab of size: ", size,
" for requested ", req_size,
" total: ", get_total_size());
169 return { ptr, [
this, size](
void* p) {
170 if (allocator_destroyed) {
174 this->release(p, size);
178 if (req_size >
static_cast<size_t>(1024 * 1024)) {
179 dbg_info(
"WARNING: Allocating unmanaged memory slab of size: ", req_size);
181 if (req_size % 32 == 0) {
182 return { aligned_alloc(32, req_size), aligned_free };
188size_t SlabAllocator::get_total_size()
190 return std::accumulate(memory_store.begin(), memory_store.end(),
size_t{ 0 }, [](
size_t acc,
const auto& kv) {
191 return acc + kv.first * kv.second.size();
195void SlabAllocator::release(
void* ptr,
size_t size)
197#ifndef NO_MULTITHREADING
200 memory_store[size].push_back(ptr);
204SlabAllocator allocator;
210 allocator.init(circuit_subgroup_size);
215 return allocator.get(size);
221#ifndef NO_MULTITHREADING
224 manual_slabs[slab.get()] = slab;
230 if (allocator_destroyed) {
234#ifndef NO_MULTITHREADING
237 manual_slabs.erase(p);
void tracy_free(void *mem)
void * tracy_malloc(size_t size)
Entry point for Barretenberg command-line interface.
void * get_mem_slab_raw(size_t size)
std::shared_ptr< void > get_mem_slab(size_t size)
void init_slab_allocator(size_t circuit_subgroup_size)
void free_mem_slab_raw(void *p)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept