Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
backing_memory.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
10#include "unistd.h"
11#include <atomic>
12#include <cstring>
13#include <fcntl.h>
14#include <filesystem>
15#include <memory>
16#ifndef __wasm__
17#include <sys/mman.h>
18#endif
19
20// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
21extern bool slow_low_memory;
22
23// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
24extern size_t storage_budget;
25
26// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
27extern std::atomic<size_t> current_storage_usage;
28
29// Parse storage size string (e.g., "500m", "2g", "1024k")
30size_t parse_size_string(const std::string& size_str);
31
32template <typename Fr> struct BackingMemory {
33 // Common raw data pointer used by all storage types
34 Fr* raw_data = nullptr;
35
36#ifndef __wasm__
37 // File-backed data substruct with cleanup metadata
39 size_t file_size;
40 std::string filename;
41 int fd;
43
45 {
46 if (raw_data_ptr != nullptr && file_size > 0) {
47 munmap(raw_data_ptr, file_size);
49 }
50 if (fd >= 0) {
51 close(fd);
52 }
53 if (!filename.empty()) {
54 std::filesystem::remove(filename);
55 }
56 }
57 };
59#endif
60 // Aligned memory data substruct
62
63 BackingMemory() = default;
64
65 BackingMemory(const BackingMemory&) = default;
67
68 BackingMemory(BackingMemory&& other) noexcept
69 : raw_data(other.raw_data)
70#ifndef __wasm__
71 , file_backed(std::move(other.file_backed))
72#endif
73 , aligned_memory(std::move(other.aligned_memory))
74 {
75 other.raw_data = nullptr;
76 }
77
79 {
80 if (this != &other) {
81 raw_data = other.raw_data;
82#ifndef __wasm__
83 file_backed = std::move(other.file_backed);
84#endif
85 aligned_memory = std::move(other.aligned_memory);
86 other.raw_data = nullptr;
87 }
88 return *this;
89 }
90
91 // Allocate memory, preferring file-backed if in low memory mode
92 static BackingMemory allocate(size_t size)
93 {
95#ifndef __wasm__
96 if (slow_low_memory) {
98 return memory;
99 }
100 }
101#endif
103 return memory;
104 }
105
106 ~BackingMemory() = default;
107
108 private:
109 static void allocate_aligned(BackingMemory& memory, size_t size)
110 {
111 // Fr has alignas on it so this is fine post c++20.
112 memory.aligned_memory = std::make_shared<Fr[]>(size);
113 memory.raw_data = memory.aligned_memory.get();
114 }
115
116#ifndef __wasm__
118 {
119 if (size == 0) {
120 return false;
121 }
122
123 size_t required_bytes = size * sizeof(Fr);
124 size_t current_usage = current_storage_usage.load();
125
126 // Check if we're under the storage budget
127 if (current_usage + required_bytes > storage_budget) {
128 return false;
129 }
130
131 size_t file_size = required_bytes;
132 static std::atomic<size_t> file_counter{ 0 };
133 size_t id = file_counter.fetch_add(1);
134
135 std::filesystem::path temp_dir;
136 try {
137 temp_dir = std::filesystem::temp_directory_path();
138 } catch (const std::exception&) {
139 temp_dir = std::filesystem::current_path();
140 }
141
142 std::string filename = temp_dir / ("poly-mmap-" + std::to_string(getpid()) + "-" + std::to_string(id));
143
144 int fd = open(filename.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0644);
145 if (fd < 0) {
146 return false;
147 }
148
149 if (ftruncate(fd, static_cast<off_t>(file_size)) != 0) {
150 close(fd);
151 std::filesystem::remove(filename);
152 return false;
153 }
154
155 void* addr = mmap(nullptr, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
156 if (addr == MAP_FAILED) {
157 close(fd);
158 std::filesystem::remove(filename);
159 return false;
160 }
161
162 auto file_backed_data = std::make_shared<FileBackedData>();
163 file_backed_data->file_size = file_size;
164 file_backed_data->filename = filename;
165 file_backed_data->fd = fd;
166 file_backed_data->raw_data_ptr = static_cast<Fr*>(addr);
167
168 memory.raw_data = static_cast<Fr*>(addr);
169 memory.file_backed = std::move(file_backed_data);
170
171 current_storage_usage.fetch_add(required_bytes);
172
173 return true;
174 }
175#endif
176};
size_t parse_size_string(const std::string &size_str)
std::atomic< size_t > current_storage_usage
bool slow_low_memory
size_t storage_budget
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
Curve::ScalarField Fr
MemoryStore memory
~BackingMemory()=default
BackingMemory()=default
static bool try_allocate_file_backed(BackingMemory &memory, size_t size)
static void allocate_aligned(BackingMemory &memory, size_t size)
std::shared_ptr< Fr[]> aligned_memory
BackingMemory & operator=(const BackingMemory &)=default
static BackingMemory allocate(size_t size)
BackingMemory(BackingMemory &&other) noexcept
BackingMemory(const BackingMemory &)=default
BackingMemory & operator=(BackingMemory &&other) noexcept
std::shared_ptr< FileBackedData > file_backed