aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/perf_namestore_api_import.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/perf_namestore_api_import.c')
-rw-r--r--src/namestore/perf_namestore_api_import.c457
1 files changed, 457 insertions, 0 deletions
diff --git a/src/namestore/perf_namestore_api_import.c b/src/namestore/perf_namestore_api_import.c
new file mode 100644
index 000000000..a2c989ebf
--- /dev/null
+++ b/src/namestore/perf_namestore_api_import.c
@@ -0,0 +1,457 @@
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 "namestore.h"
29#include "gnunet_dnsparser_lib.h"
30
31#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
32
33#define TEST_BATCH_COUNT 5
34
35#define TEST_BATCH_SIZE 1000
36
37#define TEST_RECORD_COUNT TEST_BATCH_COUNT * TEST_BATCH_SIZE
38
39/**
40 * A #BENCHMARK_SIZE of 1000 takes less than a minute on a reasonably
41 * modern system, so 30 minutes should be OK even for very, very
42 * slow systems.
43 */
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
45
46/**
47 * The runtime of the benchmark is expected to be linear
48 * for the iteration phase with a *good* database. The FLAT
49 * database uses a quadratic retrieval algorithm,
50 * hence it should be quadratic in the size.
51 */
52#define BENCHMARK_SIZE 1000
53
54/**
55 * Maximum record size
56 */
57#define MAX_REC_SIZE 500
58
59/**
60 * How big are the blocks we fetch? Note that the first block is
61 * always just 1 record set per current API. Smaller block
62 * sizes will make quadratic iteration-by-offset penalties
63 * more pronounced.
64 */
65#define BLOCK_SIZE 100
66
67static struct GNUNET_NAMESTORE_Handle *nsh;
68
69static struct GNUNET_SCHEDULER_Task *timeout_task;
70
71static struct GNUNET_SCHEDULER_Task *t;
72
73static struct GNUNET_IDENTITY_PrivateKey privkey;
74
75static struct GNUNET_NAMESTORE_QueueEntry *qe;
76
77static int res;
78
79static unsigned int left_until_next;
80
81static uint8_t seen[1 + BENCHMARK_SIZE / 8];
82
83static struct GNUNET_TIME_Absolute start;
84
85const struct GNUNET_GNSRECORD_Data *a_rd[TEST_RECORD_COUNT];
86
87unsigned int a_rd_count[TEST_RECORD_COUNT];
88
89const char *a_label[TEST_RECORD_COUNT];
90
91int single_put_pos;
92
93static int bulk_count = 0;
94
95
96/**
97 * Terminate everything
98 *
99 * @param cls NULL
100 */
101static void
102end (void *cls)
103{
104 (void) cls;
105 if (NULL != qe)
106 {
107 GNUNET_NAMESTORE_cancel (qe);
108 qe = NULL;
109 }
110 if (NULL != nsh)
111 {
112 GNUNET_NAMESTORE_disconnect (nsh);
113 nsh = NULL;
114 }
115 if (NULL != t)
116 {
117 GNUNET_SCHEDULER_cancel (t);
118 t = NULL;
119 }
120 if (NULL != timeout_task)
121 {
122 GNUNET_SCHEDULER_cancel (timeout_task);
123 timeout_task = NULL;
124 }
125}
126
127
128/**
129 * End with timeout. As this is a benchmark, we do not
130 * fail hard but return "skipped".
131 */
132static void
133timeout (void *cls)
134{
135 (void) cls;
136 timeout_task = NULL;
137 GNUNET_SCHEDULER_shutdown ();
138 res = 77;
139}
140
141
142static struct GNUNET_GNSRECORD_Data *
143create_record (unsigned int count)
144{
145 struct GNUNET_GNSRECORD_Data *rd;
146
147 rd = GNUNET_malloc (count + sizeof(struct GNUNET_GNSRECORD_Data));
148 rd->expiration_time = GNUNET_TIME_relative_to_absolute (
149 GNUNET_TIME_UNIT_HOURS).abs_value_us;
150 rd->record_type = TEST_RECORD_TYPE;
151 rd->data_size = count;
152 rd->data = (void *) &rd[1];
153 rd->flags = 0;
154 memset (&rd[1],
155 'a',
156 count);
157 return rd;
158}
159
160
161static void
162fail_cb (void *cls)
163{
164 res = 2;
165 GNUNET_break (0);
166 GNUNET_SCHEDULER_shutdown ();
167}
168
169static void
170publish_records_single (void *cls);
171
172static void
173commit_cont (void *cls,
174 int32_t success,
175 const char *emsg)
176{
177 struct GNUNET_TIME_Relative delay;
178
179 (void) cls;
180 qe = NULL;
181 if (GNUNET_OK != success)
182 {
183 GNUNET_break (0);
184 GNUNET_SCHEDULER_shutdown ();
185 return;
186 }
187 single_put_pos++;
188 delay = GNUNET_TIME_absolute_get_duration (start);
189 fprintf (stdout,
190 "BULK-TX: Publishing %u records took %s\n",
191 TEST_RECORD_COUNT,
192 GNUNET_STRINGS_relative_time_to_string (delay,
193 GNUNET_YES));
194 GNUNET_SCHEDULER_shutdown ();
195}
196
197static void
198put_cont_bulk_tx (void *cls,
199 int32_t success,
200 const char *emsg)
201{
202 qe = NULL;
203 if (GNUNET_OK != success)
204 {
205 GNUNET_break (0);
206 GNUNET_SCHEDULER_shutdown ();
207 return;
208 }
209 qe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont, NULL);
210}
211
212
213static void
214publish_records_bulk_tx (void *cls);
215
216static void
217reput_cont_bulk_tx (void *cls,
218 int32_t success,
219 const char *emsg)
220{
221 (void) cls;
222 qe = NULL;
223 if (GNUNET_OK != success)
224 {
225 GNUNET_break (0);
226 GNUNET_SCHEDULER_shutdown ();
227 return;
228 }
229 t = GNUNET_SCHEDULER_add_now (&publish_records_bulk_tx, NULL);
230
231
232}
233
234static void
235publish_records_bulk_tx (void *cls)
236{
237 t = NULL;
238 qe = GNUNET_NAMESTORE_records_store2 (nsh,
239 &privkey,
240 TEST_BATCH_SIZE,
241 &a_label[bulk_count * TEST_BATCH_SIZE],
242 &a_rd_count[bulk_count * TEST_BATCH_SIZE],
243 &a_rd[bulk_count * TEST_BATCH_SIZE],
244 (bulk_count == TEST_BATCH_COUNT - 1) ? &put_cont_bulk_tx :
245 &reput_cont_bulk_tx,
246 NULL);
247 bulk_count++;
248
249}
250
251
252static void
253begin_cont (void *cls,
254 int32_t success,
255 const char *emsg)
256{
257 qe = GNUNET_NAMESTORE_records_store2 (nsh,
258 &privkey,
259 TEST_BATCH_SIZE,
260 &a_label[bulk_count * TEST_BATCH_SIZE],
261 &a_rd_count[bulk_count * TEST_BATCH_SIZE],
262 &a_rd[bulk_count * TEST_BATCH_SIZE],
263 (bulk_count == TEST_BATCH_COUNT - 1) ? &put_cont_bulk_tx :
264 &reput_cont_bulk_tx,
265 NULL);
266 bulk_count++;
267
268}
269
270static void
271put_cont_bulk (void *cls,
272 int32_t success,
273 const char *emsg)
274{
275 struct GNUNET_TIME_Relative delay;
276
277 (void) cls;
278 qe = NULL;
279 if (GNUNET_OK != success)
280 {
281 GNUNET_break (0);
282 GNUNET_SCHEDULER_shutdown ();
283 return;
284 }
285
286 delay = GNUNET_TIME_absolute_get_duration (start);
287 fprintf (stdout,
288 "BULK: Publishing %u records took %s\n",
289 TEST_RECORD_COUNT,
290 GNUNET_STRINGS_relative_time_to_string (delay,
291 GNUNET_YES));
292 start = GNUNET_TIME_absolute_get ();
293 bulk_count = 0;
294 qe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, NULL);
295
296}
297
298static void
299publish_records_bulk (void *cls);
300
301static void
302reput_cont_bulk (void *cls,
303 int32_t success,
304 const char *emsg)
305{
306 struct GNUNET_TIME_Relative delay;
307
308 (void) cls;
309 qe = NULL;
310 if (GNUNET_OK != success)
311 {
312 GNUNET_break (0);
313 GNUNET_SCHEDULER_shutdown ();
314 return;
315 }
316 t = GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL);
317
318}
319
320
321static void
322publish_records_bulk (void *cls)
323{
324 (void) cls;
325 t = NULL;
326 qe = GNUNET_NAMESTORE_records_store2 (nsh,
327 &privkey,
328 TEST_BATCH_SIZE,
329 &a_label[bulk_count * TEST_BATCH_SIZE],
330 &a_rd_count[bulk_count * TEST_BATCH_SIZE],
331 &a_rd[bulk_count * TEST_BATCH_SIZE],
332 (bulk_count == TEST_BATCH_COUNT - 1) ? &put_cont_bulk :
333 &reput_cont_bulk,
334 NULL);
335 bulk_count++;
336}
337
338
339static void
340put_cont_single (void *cls,
341 int32_t success,
342 const char *emsg)
343{
344 struct GNUNET_TIME_Relative delay;
345 (void) cls;
346 qe = NULL;
347 if (GNUNET_OK != success)
348 {
349 GNUNET_break (0);
350 GNUNET_SCHEDULER_shutdown ();
351 return;
352 }
353 single_put_pos++;
354 if (single_put_pos == TEST_RECORD_COUNT)
355 {
356 delay = GNUNET_TIME_absolute_get_duration (start);
357 fprintf (stdout,
358 "SINGLE: Publishing %u records took %s\n",
359 TEST_RECORD_COUNT,
360 GNUNET_STRINGS_relative_time_to_string (delay,
361 GNUNET_YES));
362 start = GNUNET_TIME_absolute_get ();
363 t = GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL);
364 return;
365 }
366 t = GNUNET_SCHEDULER_add_now (&publish_records_single,
367 NULL);
368}
369
370
371static void
372publish_records_single (void *cls)
373{
374 struct GNUNET_GNSRECORD_Data *rd;
375 struct GNUNET_TIME_Relative delay;
376
377 char *label;
378
379 (void) cls;
380 t = NULL;
381 if (single_put_pos == TEST_RECORD_COUNT)
382 {
383 delay = GNUNET_TIME_absolute_get_duration (start);
384 fprintf (stdout,
385 "Publishing %u records took %s\n",
386 TEST_RECORD_COUNT,
387 GNUNET_STRINGS_relative_time_to_string (delay,
388 GNUNET_YES));
389 GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL);
390 }
391 qe = GNUNET_NAMESTORE_records_store (nsh,
392 &privkey,
393 a_label[single_put_pos],
394 a_rd_count[single_put_pos],
395 a_rd[single_put_pos],
396 &put_cont_single,
397 NULL);
398 GNUNET_free (label);
399 GNUNET_free (rd);
400}
401
402
403static void
404run (void *cls,
405 const struct GNUNET_CONFIGURATION_Handle *cfg,
406 struct GNUNET_TESTING_Peer *peer)
407{
408
409 for (int i = 0; i < TEST_RECORD_COUNT; i++)
410 {
411 a_rd[i] = create_record (1);
412 a_rd_count[i] = 1;
413 GNUNET_asprintf ((char**) &a_label[i], "label_%d", i);
414 }
415 GNUNET_SCHEDULER_add_shutdown (&end,
416 NULL);
417 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
418 &timeout,
419 NULL);
420 nsh = GNUNET_NAMESTORE_connect (cfg);
421 GNUNET_assert (NULL != nsh);
422 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
423 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
424 start = GNUNET_TIME_absolute_get ();
425 t = GNUNET_SCHEDULER_add_now (&publish_records_single,
426 NULL);
427}
428
429
430#include "test_common.c"
431
432
433int
434main (int argc,
435 char *argv[])
436{
437 const char *plugin_name;
438 char *cfg_name;
439
440 SETUP_CFG (plugin_name, cfg_name);
441 res = 1;
442 if (0 !=
443 GNUNET_TESTING_peer_run ("perf-namestore-api-import",
444 cfg_name,
445 &run,
446 NULL))
447 {
448 res = 1;
449 }
450 GNUNET_DISK_purge_cfg_dir (cfg_name,
451 "GNUNET_TEST_HOME");
452 GNUNET_free (cfg_name);
453 return res;
454}
455
456
457/* end of perf_namestore_api_zone_iteration.c */