aboutsummaryrefslogtreecommitdiff
path: root/src/service/namestore/perf_namestore_api_import.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/namestore/perf_namestore_api_import.c')
-rw-r--r--src/service/namestore/perf_namestore_api_import.c406
1 files changed, 406 insertions, 0 deletions
diff --git a/src/service/namestore/perf_namestore_api_import.c b/src/service/namestore/perf_namestore_api_import.c
new file mode 100644
index 000000000..bf8093f43
--- /dev/null
+++ b/src/service/namestore/perf_namestore_api_import.c
@@ -0,0 +1,406 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file namestore/perf_namestore_api_import.c
22 * @brief testcase for namestore: Import a lot of records
23 * @author Martin Schanzenbach
24 */
25#include "platform.h"
26#include "gnunet_namestore_service.h"
27#include "gnunet_testing_lib.h"
28#include "../service/namestore/namestore.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32#define TEST_RECORD_COUNT 10000
33
34/**
35 * A #BENCHMARK_SIZE of 1000 takes less than a minute on a reasonably
36 * modern system, so 30 minutes should be OK even for very, very
37 * slow systems.
38 */
39#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
40
41/**
42 * The runtime of the benchmark is expected to be linear
43 * for the iteration phase with a *good* database. The FLAT
44 * database uses a quadratic retrieval algorithm,
45 * hence it should be quadratic in the size.
46 */
47#define BENCHMARK_SIZE 1000
48
49/**
50 * Maximum record size
51 */
52#define MAX_REC_SIZE 500
53
54/**
55 * How big are the blocks we fetch? Note that the first block is
56 * always just 1 record set per current API. Smaller block
57 * sizes will make quadratic iteration-by-offset penalties
58 * more pronounced.
59 */
60#define BLOCK_SIZE 100
61
62static struct GNUNET_NAMESTORE_Handle *nsh;
63
64static struct GNUNET_SCHEDULER_Task *timeout_task;
65
66static struct GNUNET_SCHEDULER_Task *t;
67
68static struct GNUNET_CRYPTO_PrivateKey privkey;
69
70static struct GNUNET_NAMESTORE_QueueEntry *qe;
71
72static int res;
73
74static struct GNUNET_TIME_Absolute start;
75
76struct GNUNET_NAMESTORE_RecordInfo ri[TEST_RECORD_COUNT];
77
78int single_put_pos;
79
80static int bulk_count = 0;
81
82
83/**
84 * Terminate everything
85 *
86 * @param cls NULL
87 */
88static void
89end (void *cls)
90{
91 (void) cls;
92 if (NULL != qe)
93 {
94 GNUNET_NAMESTORE_cancel (qe);
95 qe = NULL;
96 }
97 if (NULL != nsh)
98 {
99 GNUNET_NAMESTORE_disconnect (nsh);
100 nsh = NULL;
101 }
102 if (NULL != t)
103 {
104 GNUNET_SCHEDULER_cancel (t);
105 t = NULL;
106 }
107 if (NULL != timeout_task)
108 {
109 GNUNET_SCHEDULER_cancel (timeout_task);
110 timeout_task = NULL;
111 }
112}
113
114
115/**
116 * End with timeout. As this is a benchmark, we do not
117 * fail hard but return "skipped".
118 */
119static void
120timeout (void *cls)
121{
122 (void) cls;
123 timeout_task = NULL;
124 GNUNET_SCHEDULER_shutdown ();
125 res = 77;
126}
127
128
129static struct GNUNET_GNSRECORD_Data *
130create_record (unsigned int count)
131{
132 struct GNUNET_GNSRECORD_Data *rd;
133
134 rd = GNUNET_malloc (count + sizeof(struct GNUNET_GNSRECORD_Data));
135 rd->expiration_time = GNUNET_TIME_relative_to_absolute (
136 GNUNET_TIME_UNIT_HOURS).abs_value_us;
137 rd->record_type = TEST_RECORD_TYPE;
138 rd->data_size = count;
139 rd->data = (void *) &rd[1];
140 rd->flags = 0;
141 memset (&rd[1],
142 'a',
143 count);
144 return rd;
145}
146
147
148static void
149publish_records_single (void *cls);
150
151static void
152commit_cont (void *cls,
153 enum GNUNET_ErrorCode ec)
154{
155 struct GNUNET_TIME_Relative delay;
156
157 (void) cls;
158 qe = NULL;
159 if (GNUNET_EC_NONE != ec)
160 {
161 GNUNET_break (0);
162 GNUNET_SCHEDULER_shutdown ();
163 return;
164 }
165 single_put_pos++;
166 delay = GNUNET_TIME_absolute_get_duration (start);
167 fprintf (stdout,
168 "BULK-TX: Publishing %u records took %s\n",
169 TEST_RECORD_COUNT,
170 GNUNET_STRINGS_relative_time_to_string (delay,
171 GNUNET_YES));
172 res = 0;
173 GNUNET_SCHEDULER_shutdown ();
174}
175
176static void
177publish_records_bulk_tx (void *cls);
178
179
180static void
181put_cont_bulk_tx (void *cls,
182 enum GNUNET_ErrorCode ec)
183{
184 qe = NULL;
185 if (GNUNET_EC_NONE != ec)
186 {
187 GNUNET_break (0);
188 GNUNET_SCHEDULER_shutdown ();
189 return;
190 }
191 if (bulk_count == TEST_RECORD_COUNT)
192 {
193 qe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont, NULL);
194 return;
195 }
196 t = GNUNET_SCHEDULER_add_now (&publish_records_bulk_tx, NULL);
197}
198
199
200static void
201publish_records_bulk_tx (void *cls)
202{
203 unsigned int sent_rds;
204 t = NULL;
205 qe = GNUNET_NAMESTORE_records_store2 (nsh,
206 &privkey,
207 TEST_RECORD_COUNT - bulk_count,
208 &ri[bulk_count],
209 &sent_rds,
210 &put_cont_bulk_tx,
211 NULL);
212 bulk_count += sent_rds;
213 GNUNET_assert (sent_rds != 0);
214}
215
216
217static void
218begin_cont (void *cls,
219 enum GNUNET_ErrorCode ec)
220{
221 unsigned int sent_rds;
222 qe = GNUNET_NAMESTORE_records_store2 (nsh,
223 &privkey,
224 TEST_RECORD_COUNT - bulk_count,
225 &ri[bulk_count],
226 &sent_rds,
227 &put_cont_bulk_tx,
228 NULL);
229 bulk_count += sent_rds;
230 GNUNET_assert (sent_rds != 0);
231}
232
233static void
234publish_records_bulk (void *cls);
235
236static void
237put_cont_bulk (void *cls,
238 enum GNUNET_ErrorCode ec)
239{
240 struct GNUNET_TIME_Relative delay;
241
242 (void) cls;
243 qe = NULL;
244 if (GNUNET_EC_NONE != ec)
245 {
246 GNUNET_break (0);
247 GNUNET_SCHEDULER_shutdown ();
248 return;
249 }
250
251 if (bulk_count == TEST_RECORD_COUNT)
252 {
253 delay = GNUNET_TIME_absolute_get_duration (start);
254 fprintf (stdout,
255 "BULK: Publishing %u records took %s\n",
256 TEST_RECORD_COUNT,
257 GNUNET_STRINGS_relative_time_to_string (delay,
258 GNUNET_YES));
259 start = GNUNET_TIME_absolute_get ();
260 bulk_count = 0;
261 qe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, NULL);
262 return;
263 }
264 (void) cls;
265 qe = NULL;
266 if (GNUNET_EC_NONE != ec)
267 {
268 GNUNET_break (0);
269 GNUNET_SCHEDULER_shutdown ();
270 return;
271 }
272 t = GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL);
273}
274
275static void
276publish_records_bulk (void *cls)
277{
278 static unsigned int sent_rds = 0;
279 (void) cls;
280 t = NULL;
281 qe = GNUNET_NAMESTORE_records_store2 (nsh,
282 &privkey,
283 TEST_RECORD_COUNT - bulk_count,
284 &ri[bulk_count],
285 &sent_rds,
286 &put_cont_bulk,
287 NULL);
288 bulk_count += sent_rds;
289 GNUNET_assert (sent_rds != 0);
290}
291
292
293static void
294put_cont_single (void *cls,
295 enum GNUNET_ErrorCode ec)
296{
297 struct GNUNET_TIME_Relative delay;
298 (void) cls;
299 qe = NULL;
300 if (GNUNET_EC_NONE != ec)
301 {
302 GNUNET_break (0);
303 GNUNET_SCHEDULER_shutdown ();
304 return;
305 }
306 single_put_pos++;
307 if (single_put_pos == TEST_RECORD_COUNT)
308 {
309 delay = GNUNET_TIME_absolute_get_duration (start);
310 fprintf (stdout,
311 "SINGLE: Publishing %u records took %s\n",
312 TEST_RECORD_COUNT,
313 GNUNET_STRINGS_relative_time_to_string (delay,
314 GNUNET_YES));
315 start = GNUNET_TIME_absolute_get ();
316 t = GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL);
317 return;
318 }
319 t = GNUNET_SCHEDULER_add_now (&publish_records_single,
320 NULL);
321}
322
323
324static void
325publish_records_single (void *cls)
326{
327 struct GNUNET_TIME_Relative delay;
328
329 (void) cls;
330 t = NULL;
331 if (single_put_pos == TEST_RECORD_COUNT)
332 {
333 delay = GNUNET_TIME_absolute_get_duration (start);
334 fprintf (stdout,
335 "Publishing %u records took %s\n",
336 TEST_RECORD_COUNT,
337 GNUNET_STRINGS_relative_time_to_string (delay,
338 GNUNET_YES));
339 GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL);
340 }
341 qe = GNUNET_NAMESTORE_records_store (nsh,
342 &privkey,
343 ri[single_put_pos].a_label,
344 ri[single_put_pos].a_rd_count,
345 ri[single_put_pos].a_rd,
346 &put_cont_single,
347 NULL);
348}
349
350
351static void
352run (void *cls,
353 const struct GNUNET_CONFIGURATION_Handle *cfg,
354 struct GNUNET_TESTING_Peer *peer)
355{
356
357 for (int i = 0; i < TEST_RECORD_COUNT; i++)
358 {
359 ri[i].a_rd = create_record (1);
360 ri[i].a_rd_count = 1;
361 GNUNET_asprintf ((char**) &ri[i].a_label, "label_%d", i);
362 }
363 GNUNET_SCHEDULER_add_shutdown (&end,
364 NULL);
365 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
366 &timeout,
367 NULL);
368 nsh = GNUNET_NAMESTORE_connect (cfg);
369 GNUNET_assert (NULL != nsh);
370 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
371 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
372 start = GNUNET_TIME_absolute_get ();
373 t = GNUNET_SCHEDULER_add_now (&publish_records_single,
374 NULL);
375}
376
377
378#include "test_common.c"
379
380
381int
382main (int argc,
383 char *argv[])
384{
385 char *plugin_name;
386 char *cfg_name;
387
388 SETUP_CFG2 ("perf_namestore_api_%s.conf", plugin_name, cfg_name);
389 res = 1;
390 if (0 !=
391 GNUNET_TESTING_peer_run ("perf-namestore-api-import",
392 cfg_name,
393 &run,
394 NULL))
395 {
396 res = 1;
397 }
398 GNUNET_DISK_purge_cfg_dir (cfg_name,
399 "GNUNET_TEST_HOME");
400 GNUNET_free (plugin_name);
401 GNUNET_free (cfg_name);
402 return res;
403}
404
405
406/* end of perf_namestore_api_zone_iteration.c */