Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
indexed_tree.bench.cpp
Go to the documentation of this file.
10#include <benchmark/benchmark.h>
11#include <filesystem>
12#include <memory>
13#include <vector>
14
15using namespace benchmark;
16using namespace bb::crypto::merkle_tree;
17
19
21
22const size_t TREE_DEPTH = 40;
23const size_t MAX_BATCH_SIZE = 64;
24
25template <typename TreeType> void add_values(TreeType& tree, const std::vector<NullifierLeafValue>& values)
26{
27 Signal signal(1);
28 bool success = true;
29 std::string error_message;
30 typename TreeType::AddCompletionCallback completion = [&](const auto& result) -> void {
31 success = result.success;
32 error_message = result.message;
33 signal.signal_level(0);
34 };
35
36 tree.add_or_update_values(values, completion);
37 signal.wait_for_level(0);
38 if (!success) {
39 throw std::runtime_error(format("Failed to add values: ", error_message));
40 }
41}
42
43template <typename TreeType> void add_values_with_witness(TreeType& tree, const std::vector<NullifierLeafValue>& values)
44{
45 bool success = true;
46 std::string error_message;
47 Signal signal(1);
48 typename TreeType::AddCompletionCallbackWithWitness completion = [&](const auto& result) -> void {
49 success = result.success;
50 error_message = result.message;
51 signal.signal_level(0);
52 };
53
54 tree.add_or_update_values(values, completion);
55 signal.wait_for_level(0);
56 if (!success) {
57 throw std::runtime_error(format("Failed to add values with witness: ", error_message));
58 }
59}
60
61template <typename TreeType> void add_values_sequentially(TreeType& tree, const std::vector<NullifierLeafValue>& values)
62{
63 bool success = true;
64 std::string error_message;
65 Signal signal(1);
66 typename TreeType::AddCompletionCallback completion = [&](const auto& result) -> void {
67 success = result.success;
68 error_message = result.message;
69 signal.signal_level(0);
70 };
71
72 tree.add_or_update_values_sequentially(values, completion);
73 signal.wait_for_level(0);
74 if (!success) {
75 throw std::runtime_error(format("Failed to add values sequentially: ", error_message));
76 }
77}
78
79template <typename TreeType>
81{
82 bool success = true;
83 std::string error_message;
84 Signal signal(1);
85 typename TreeType::AddSequentiallyCompletionCallbackWithWitness completion = [&](const auto& result) -> void {
86 success = result.success;
87 error_message = result.message;
88 signal.signal_level(0);
89 };
90
91 tree.add_or_update_values_sequentially(values, completion);
92 signal.wait_for_level(0);
93 if (!success) {
94 throw std::runtime_error(format("Failed to add values sequentially with witness: ", error_message));
95 }
96}
97
99
100template <typename TreeType, InsertionStrategy strategy> void multi_thread_indexed_tree_bench(State& state) noexcept
101{
102 const size_t batch_size = size_t(state.range(0));
103 const size_t depth = TREE_DEPTH;
104
105 std::string directory = random_temp_directory();
106 std::string name = random_string();
107 std::filesystem::create_directories(directory);
108 uint32_t num_threads = 16;
109
110 LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(directory, name, 1024 * 1024, num_threads);
113 TreeType tree = TreeType(std::move(store), workers, batch_size);
114
115 const size_t initial_size = 1024 * 16;
116 std::vector<NullifierLeafValue> initial_batch(initial_size);
117 for (size_t i = 0; i < initial_size; ++i) {
118 initial_batch[i] = fr(random_engine.get_random_uint256());
119 }
120 if (strategy == SEQUENTIAL) {
121 add_values_sequentially(tree, initial_batch);
122 } else {
123 add_values(tree, initial_batch);
124 }
125
126 for (auto _ : state) {
127 state.PauseTiming();
128 std::vector<NullifierLeafValue> values(batch_size);
129 for (size_t i = 0; i < batch_size; ++i) {
130 values[i] = fr(random_engine.get_random_uint256());
131 }
132 state.ResumeTiming();
133 if (strategy == SEQUENTIAL) {
134 add_values_sequentially(tree, values);
135 } else {
136 add_values(tree, values);
137 }
138 }
139}
140
141template <typename TreeType, InsertionStrategy strategy> void single_thread_indexed_tree_bench(State& state) noexcept
142{
143 const size_t batch_size = size_t(state.range(0));
144 const size_t depth = TREE_DEPTH;
145
146 std::string directory = random_temp_directory();
147 std::string name = random_string();
148 std::filesystem::create_directories(directory);
149 uint32_t num_threads = 1;
150
151 LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(directory, name, 1024 * 1024, num_threads);
154 TreeType tree = TreeType(std::move(store), workers, batch_size);
155
156 const size_t initial_size = 1024 * 16;
157 std::vector<NullifierLeafValue> initial_batch(initial_size);
158 for (size_t i = 0; i < initial_size; ++i) {
159 initial_batch[i] = fr(random_engine.get_random_uint256());
160 }
161 if (strategy == SEQUENTIAL) {
162 add_values_sequentially(tree, initial_batch);
163 } else {
164 add_values(tree, initial_batch);
165 }
166
167 for (auto _ : state) {
168 state.PauseTiming();
169 std::vector<NullifierLeafValue> values(batch_size);
170 for (size_t i = 0; i < batch_size; ++i) {
171 values[i] = fr(random_engine.get_random_uint256());
172 }
173 state.ResumeTiming();
174 if (strategy == SEQUENTIAL) {
175 add_values_sequentially(tree, values);
176 } else {
177 add_values(tree, values);
178 }
179 }
180}
181
182template <typename TreeType, InsertionStrategy strategy>
184{
185 const size_t batch_size = size_t(state.range(0));
186 const size_t depth = TREE_DEPTH;
187
188 std::string directory = random_temp_directory();
189 std::string name = random_string();
190 std::filesystem::create_directories(directory);
191 uint32_t num_threads = 16;
192
193 LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(directory, name, 1024 * 1024, num_threads);
196 TreeType tree = TreeType(std::move(store), workers, batch_size);
197
198 const size_t initial_size = 1024 * 16;
199 std::vector<NullifierLeafValue> initial_batch(initial_size);
200 for (size_t i = 0; i < initial_size; ++i) {
201 initial_batch[i] = fr(random_engine.get_random_uint256());
202 }
203 if (strategy == SEQUENTIAL) {
204 add_values_sequentially(tree, initial_batch);
205 } else {
206 add_values(tree, initial_batch);
207 }
208
209 for (auto _ : state) {
210 state.PauseTiming();
211 std::vector<NullifierLeafValue> values(batch_size);
212 for (size_t i = 0; i < batch_size; ++i) {
213 values[i] = fr(random_engine.get_random_uint256());
214 }
215 state.ResumeTiming();
216 if (strategy == SEQUENTIAL) {
218 } else {
219 add_values_with_witness(tree, values);
220 }
221 }
222}
223
224template <typename TreeType, InsertionStrategy strategy>
226{
227 const size_t batch_size = size_t(state.range(0));
228 const size_t depth = TREE_DEPTH;
229
230 std::string directory = random_temp_directory();
231 std::string name = random_string();
232 std::filesystem::create_directories(directory);
233 uint32_t num_threads = 1;
234
235 LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(directory, name, 1024 * 1024, num_threads);
238 TreeType tree = TreeType(std::move(store), workers, batch_size);
239
240 const size_t initial_size = 1024 * 16;
241 std::vector<NullifierLeafValue> initial_batch(initial_size);
242 for (size_t i = 0; i < initial_size; ++i) {
243 initial_batch[i] = fr(random_engine.get_random_uint256());
244 }
245 if (strategy == SEQUENTIAL) {
246 add_values_sequentially(tree, initial_batch);
247 } else {
248 add_values(tree, initial_batch);
249 }
250
251 for (auto _ : state) {
252 state.PauseTiming();
253 std::vector<NullifierLeafValue> values(batch_size);
254 for (size_t i = 0; i < batch_size; ++i) {
255 values[i] = fr(random_engine.get_random_uint256());
256 }
257 state.ResumeTiming();
258 if (strategy == SEQUENTIAL) {
260 } else {
261 add_values_with_witness(tree, values);
262 }
263 }
264}
265
266BENCHMARK(single_thread_indexed_tree_with_witness_bench<Poseidon2, BATCH>)
267 ->Unit(benchmark::kMillisecond)
268 ->RangeMultiplier(2)
269 ->Range(2, MAX_BATCH_SIZE)
270 ->Iterations(1000);
271
272BENCHMARK(single_thread_indexed_tree_with_witness_bench<Poseidon2, BATCH>)
273 ->Unit(benchmark::kMillisecond)
274 ->RangeMultiplier(2)
275 ->Range(512, 8192)
276 ->Iterations(10);
277
278BENCHMARK(single_thread_indexed_tree_with_witness_bench<Poseidon2, SEQUENTIAL>)
279 ->Unit(benchmark::kMillisecond)
280 ->RangeMultiplier(2)
281 ->Range(2, MAX_BATCH_SIZE)
282 ->Iterations(1000);
283
284BENCHMARK(single_thread_indexed_tree_with_witness_bench<Poseidon2, SEQUENTIAL>)
285 ->Unit(benchmark::kMillisecond)
286 ->RangeMultiplier(2)
287 ->Range(512, 8192)
288 ->Iterations(10);
289
290BENCHMARK(multi_thread_indexed_tree_with_witness_bench<Poseidon2, BATCH>)
291 ->Unit(benchmark::kMillisecond)
292 ->RangeMultiplier(2)
293 ->Range(2, MAX_BATCH_SIZE)
294 ->Iterations(1000);
295
296BENCHMARK(multi_thread_indexed_tree_with_witness_bench<Poseidon2, BATCH>)
297 ->Unit(benchmark::kMillisecond)
298 ->RangeMultiplier(2)
299 ->Range(512, 8192)
300 ->Iterations(10);
301
302BENCHMARK(multi_thread_indexed_tree_with_witness_bench<Poseidon2, SEQUENTIAL>)
303 ->Unit(benchmark::kMillisecond)
304 ->RangeMultiplier(2)
305 ->Range(2, MAX_BATCH_SIZE)
306 ->Iterations(1000);
307
308BENCHMARK(multi_thread_indexed_tree_with_witness_bench<Poseidon2, SEQUENTIAL>)
309 ->Unit(benchmark::kMillisecond)
310 ->RangeMultiplier(2)
311 ->Range(512, 8192)
312 ->Iterations(10);
313
314BENCHMARK(single_thread_indexed_tree_bench<Poseidon2, BATCH>)
315 ->Unit(benchmark::kMillisecond)
316 ->RangeMultiplier(2)
317 ->Range(2, MAX_BATCH_SIZE)
318 ->Iterations(1000);
319
320BENCHMARK(single_thread_indexed_tree_bench<Poseidon2, BATCH>)
321 ->Unit(benchmark::kMillisecond)
322 ->RangeMultiplier(2)
323 ->Range(512, 8192)
324 ->Iterations(10);
325
326BENCHMARK(single_thread_indexed_tree_bench<Poseidon2, SEQUENTIAL>)
327 ->Unit(benchmark::kMillisecond)
328 ->RangeMultiplier(2)
329 ->Range(2, MAX_BATCH_SIZE)
330 ->Iterations(1000);
331
332BENCHMARK(single_thread_indexed_tree_bench<Poseidon2, SEQUENTIAL>)
333 ->Unit(benchmark::kMillisecond)
334 ->RangeMultiplier(2)
335 ->Range(512, 8192)
336 ->Iterations(10);
337
338BENCHMARK(multi_thread_indexed_tree_bench<Poseidon2, BATCH>)
339 ->Unit(benchmark::kMillisecond)
340 ->RangeMultiplier(2)
341 ->Range(2, MAX_BATCH_SIZE)
342 ->Iterations(1000);
343
344BENCHMARK(multi_thread_indexed_tree_bench<Poseidon2, BATCH>)
345 ->Unit(benchmark::kMillisecond)
346 ->RangeMultiplier(2)
347 ->Range(512, 8192)
348 ->Iterations(100);
349
350BENCHMARK(multi_thread_indexed_tree_bench<Poseidon2, SEQUENTIAL>)
351 ->Unit(benchmark::kMillisecond)
352 ->RangeMultiplier(2)
353 ->Range(2, MAX_BATCH_SIZE)
354 ->Iterations(1000);
355
356BENCHMARK(multi_thread_indexed_tree_bench<Poseidon2, SEQUENTIAL>)
357 ->Unit(benchmark::kMillisecond)
358 ->RangeMultiplier(2)
359 ->Range(512, 8192)
360 ->Iterations(100);
361
Native Poseidon2 hash function implementation.
Definition poseidon2.hpp:22
Implements a simple append-only merkle tree All methods are asynchronous unless specified as otherwis...
Serves as a key-value node store for merkle trees. Caches all changes in memory before persisting the...
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
std::shared_ptr< LMDBTreeStore > SharedPtr
Used in parallel insertions in the the IndexedTree. Workers signal to other following workes as they ...
Definition signal.hpp:17
void signal_level(uint32_t level=0)
Signals that the given level has been passed.
Definition signal.hpp:54
void wait_for_level(uint32_t level=0)
Causes the thread to wait until the required level has been signalled.
Definition signal.hpp:40
std::string format(Args... args)
Definition log.hpp:23
ContentAddressedAppendOnlyTree< Store, Poseidon2HashPolicy > TreeType
void single_thread_indexed_tree_with_witness_bench(State &state) noexcept
void add_values_sequentially(TreeType &tree, const std::vector< NullifierLeafValue > &values)
void add_values_with_witness(TreeType &tree, const std::vector< NullifierLeafValue > &values)
const size_t TREE_DEPTH
BENCHMARK_MAIN()
const size_t MAX_BATCH_SIZE
void multi_thread_indexed_tree_bench(State &state) noexcept
void single_thread_indexed_tree_bench(State &state) noexcept
void add_values_sequentially_with_witness(TreeType &tree, const std::vector< NullifierLeafValue > &values)
InsertionStrategy
void multi_thread_indexed_tree_with_witness_bench(State &state) noexcept
void add_values(TreeType &tree, const std::vector< NullifierLeafValue > &values)
std::string random_temp_directory()
Definition fixtures.hpp:37
std::string random_string()
Definition fixtures.hpp:30
field< Bn254FrParams > fr
Definition fr.hpp:155
BENCHMARK(bench_commit_structured_random_poly< curve::BN254 >) -> Unit(benchmark::kMillisecond)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13