aboutsummaryrefslogtreecommitdiff
path: root/src/service/setu/perf_setu_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/setu/perf_setu_api.c')
-rw-r--r--src/service/setu/perf_setu_api.c473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/service/setu/perf_setu_api.c b/src/service/setu/perf_setu_api.c
new file mode 100644
index 000000000..7f4d64f74
--- /dev/null
+++ b/src/service/setu/perf_setu_api.c
@@ -0,0 +1,473 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 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/**
22 * @file set/test_setu_api.c
23 * @brief testcase for setu_api.c
24 * @author Florian Dold
25 * @author Elias Summermatter
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_setu_service.h"
31#include <sys/sysinfo.h>
32#include <pthread.h>
33
34
35static struct GNUNET_PeerIdentity local_id;
36
37static struct GNUNET_HashCode app_id;
38
39static struct GNUNET_SETU_Handle *set1;
40
41static struct GNUNET_SETU_Handle *set2;
42
43static struct GNUNET_SETU_ListenHandle *listen_handle;
44
45static struct GNUNET_SETU_OperationHandle *oh1;
46
47static struct GNUNET_SETU_OperationHandle *oh2;
48
49static const struct GNUNET_CONFIGURATION_Handle *config;
50
51static int ret;
52
53static struct GNUNET_SCHEDULER_Task *tt;
54
55
56/**
57 * Handles configuration file for setu performance test
58 *
59 */
60static struct GNUNET_CONFIGURATION_Handle *setu_cfg;
61
62
63static void
64result_cb_set1 (void *cls,
65 const struct GNUNET_SETU_Element *element,
66 uint64_t size,
67 enum GNUNET_SETU_Status status)
68{
69 switch (status)
70 {
71 case GNUNET_SETU_STATUS_ADD_LOCAL:
72 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: got element\n");
73 break;
74
75 case GNUNET_SETU_STATUS_FAILURE:
76 GNUNET_break (0);
77 oh1 = NULL;
78 fprintf (stderr, "set 1: received failure status!\n");
79 ret = 1;
80 if (NULL != tt)
81 {
82 GNUNET_SCHEDULER_cancel (tt);
83 tt = NULL;
84 }
85 GNUNET_SCHEDULER_shutdown ();
86 break;
87
88 case GNUNET_SETU_STATUS_DONE:
89 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: done\n");
90 oh1 = NULL;
91 if (NULL != set1)
92 {
93 GNUNET_SETU_destroy (set1);
94 set1 = NULL;
95 }
96 if (NULL == set2)
97 {
98 GNUNET_SCHEDULER_cancel (tt);
99 tt = NULL;
100 GNUNET_SCHEDULER_shutdown ();
101 }
102 break;
103
104 default:
105 GNUNET_assert (0);
106 }
107}
108
109
110static void
111result_cb_set2 (void *cls,
112 const struct GNUNET_SETU_Element *element,
113 uint64_t size,
114 enum GNUNET_SETU_Status status)
115{
116 switch (status)
117 {
118 case GNUNET_SETU_STATUS_ADD_LOCAL:
119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: got element\n");
120 break;
121
122 case GNUNET_SETU_STATUS_FAILURE:
123 GNUNET_break (0);
124 oh2 = NULL;
125 fprintf (stderr, "set 2: received failure status\n");
126 GNUNET_SCHEDULER_shutdown ();
127 ret = 1;
128 break;
129
130 case GNUNET_SETU_STATUS_DONE:
131 oh2 = NULL;
132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: done\n");
133 GNUNET_SETU_destroy (set2);
134 set2 = NULL;
135 if (NULL == set1)
136 {
137 GNUNET_SCHEDULER_cancel (tt);
138 tt = NULL;
139 GNUNET_SCHEDULER_shutdown ();
140 }
141 break;
142
143 default:
144 GNUNET_assert (0);
145 }
146}
147
148
149static void
150listen_cb (void *cls,
151 const struct GNUNET_PeerIdentity *other_peer,
152 const struct GNUNET_MessageHeader *context_msg,
153 struct GNUNET_SETU_Request *request)
154{
155 GNUNET_assert (NULL != context_msg);
156 GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "listen cb called\n");
158 oh2 = GNUNET_SETU_accept (request,
159 (struct GNUNET_SETU_Option[]){ 0 },
160 &result_cb_set2,
161 NULL);
162 GNUNET_SETU_commit (oh2, set2);
163}
164
165
166/**
167 * Start the set operation.
168 *
169 * @param cls closure, unused
170 */
171static void
172start (void *cls)
173{
174 struct GNUNET_MessageHeader context_msg;
175
176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting reconciliation\n");
177 context_msg.size = htons (sizeof context_msg);
178 context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
179 listen_handle = GNUNET_SETU_listen (config,
180 &app_id,
181 &listen_cb,
182 NULL);
183 oh1 = GNUNET_SETU_prepare (&local_id,
184 &app_id,
185 &context_msg,
186 (struct GNUNET_SETU_Option[]){ 0 },
187 &result_cb_set1,
188 NULL);
189 GNUNET_SETU_commit (oh1, set1);
190}
191
192
193/**
194 * Generate random byte stream
195 */
196
197unsigned char *
198gen_rdm_bytestream (size_t num_bytes)
199{
200 unsigned char *stream = GNUNET_malloc (num_bytes);
201 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, stream, num_bytes);
202 return stream;
203}
204
205
206/**
207 * Generate random sets
208 */
209
210static void
211initRandomSets (int overlap, int set1_size, int set2_size, int
212 element_size_in_bytes)
213{
214 struct GNUNET_SETU_Element element;
215 element.element_type = 0;
216
217 // Add elements to both sets
218 for (int i = 0; i < overlap; i++)
219 {
220 element.data = gen_rdm_bytestream (element_size_in_bytes);
221 element.size = element_size_in_bytes;
222 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
223 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
224 set1_size--;
225 set2_size--;
226 }
227 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in both sets\n");
228
229 // Add other elements to set 1
230 while (set1_size>0)
231 {
232 element.data = gen_rdm_bytestream (element_size_in_bytes);
233 element.size = element_size_in_bytes;
234 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
235 set1_size--;
236 }
237 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in set1\n");
238
239 // Add other elements to set 2
240 while (set2_size > 0)
241 {
242 element.data = gen_rdm_bytestream (element_size_in_bytes);
243 element.size = element_size_in_bytes;
244
245 if (set2_size != 1)
246 {
247 GNUNET_SETU_add_element (set2, &element,NULL, NULL);
248 }
249 else
250 {
251 GNUNET_SETU_add_element (set2, &element,&start, NULL);
252 }
253
254 set2_size--;
255 }
256 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized elements in set2\n");
257}
258
259
260/**
261 * Function run on timeout.
262 *
263 * @param cls closure
264 */
265static void
266timeout_fail (void *cls)
267{
268 tt = NULL;
269 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Testcase failed with timeout\n");
270 GNUNET_SCHEDULER_shutdown ();
271 ret = 1;
272}
273
274
275/**
276 * Function run on shutdown.
277 *
278 * @param cls closure
279 */
280static void
281do_shutdown (void *cls)
282{
283 if (NULL != tt)
284 {
285 GNUNET_SCHEDULER_cancel (tt);
286 tt = NULL;
287 }
288 if (NULL != oh1)
289 {
290 GNUNET_SETU_operation_cancel (oh1);
291 oh1 = NULL;
292 }
293 if (NULL != oh2)
294 {
295 GNUNET_SETU_operation_cancel (oh2);
296 oh2 = NULL;
297 }
298 if (NULL != set1)
299 {
300 GNUNET_SETU_destroy (set1);
301 set1 = NULL;
302 }
303 if (NULL != set2)
304 {
305 GNUNET_SETU_destroy (set2);
306 set2 = NULL;
307 }
308 if (NULL != listen_handle)
309 {
310 GNUNET_SETU_listen_cancel (listen_handle);
311 listen_handle = NULL;
312 }
313}
314
315
316/**
317 * Signature of the 'main' function for a (single-peer) testcase that
318 * is run using 'GNUNET_TESTING_peer_run'.
319 *
320 * @param cls closure
321 * @param cfg configuration of the peer that was started
322 * @param peer identity of the peer that was created
323 */
324static void
325run (void *cls,
326 const struct GNUNET_CONFIGURATION_Handle *cfg,
327 struct GNUNET_TESTING_Peer *peer)
328{
329 struct GNUNET_SETU_OperationHandle *my_oh;
330
331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332 "Running preparatory tests\n");
333 tt = GNUNET_SCHEDULER_add_delayed (
334 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
335 &timeout_fail,
336 NULL);
337 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
338
339 config = cfg;
340 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_get_peer_identity (cfg,
341 &local_id));
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "my id (from CRYPTO): %s\n",
344 GNUNET_i2s (&local_id));
345 GNUNET_TESTING_peer_get_identity (peer,
346 &local_id);
347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
348 "my id (from TESTING): %s\n",
349 GNUNET_i2s (&local_id));
350 set1 = GNUNET_SETU_create (cfg);
351 set2 = GNUNET_SETU_create (cfg);
352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
353 "Created sets %p and %p for union operation\n",
354 set1,
355 set2);
356 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
357
358 /* test if canceling an uncommitted request works! */
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "Launching and instantly stopping set operation\n");
361 my_oh = GNUNET_SETU_prepare (&local_id,
362 &app_id,
363 NULL,
364 (struct GNUNET_SETU_Option[]){ 0 },
365 NULL,
366 NULL);
367 GNUNET_SETU_operation_cancel (my_oh);
368
369 /* test the real set reconciliation */
370 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
371 "Running real set-reconciliation\n");
372 // init_set1 ();
373 // limit ~23800 element total
374 initRandomSets (490, 500,500,32);
375}
376
377
378void
379perf_thread ()
380{
381 GNUNET_TESTING_service_run ("perf_setu_api",
382 "arm",
383 "test_setu.conf",
384 &run,
385 NULL);
386
387}
388
389
390static void
391run_petf_thread (int total_runs)
392{
393 int core_count = get_nprocs_conf ();
394 pid_t child_pid, wpid;
395 int status = 0;
396
397// Father code (before child processes start)
398 for (int processed = 0; processed < total_runs;)
399 {
400 for (int id = 0; id < core_count; id++)
401 {
402 if (processed >= total_runs)
403 break;
404
405 if ((child_pid = fork ()) == 0)
406 {
407 perf_thread ();
408 exit (0);
409 }
410 processed += 1;
411 }
412 while ((wpid = wait (&status)) > 0)
413 ;
414
415 }
416}
417
418
419static void
420execute_perf ()
421{
422
423 /**
424 * Erase statfile
425 */
426 remove ("perf_stats.csv");
427 remove ("perf_failure_bucket_number_factor.csv");
428 for (int out_out_ctr = 3; out_out_ctr <= 3; out_out_ctr++)
429 {
430
431 for (int out_ctr = 20; out_ctr <= 20; out_ctr++)
432 {
433 float base = 0.1;
434 float x = out_ctr * base;
435 char factor[10];
436 char *buffer = gcvt (x, 4, factor);
437 setu_cfg = GNUNET_CONFIGURATION_create ();
438 GNUNET_CONFIGURATION_set_value_string (setu_cfg, "IBF",
439 "BUCKET_NUMBER_FACTOR",
440 buffer); // Factor default=4
441 GNUNET_CONFIGURATION_set_value_number (setu_cfg, "IBF",
442 "NUMBER_PER_BUCKET", 3); // K default=4
443 GNUNET_CONFIGURATION_set_value_string (setu_cfg, "PERFORMANCE",
444 "TRADEOFF", "2"); // default=0.25
445 GNUNET_CONFIGURATION_set_value_string (setu_cfg, "PERFORMANCE",
446 "MAX_SET_DIFF_FACTOR_DIFFERENTIAL",
447 "20000"); // default=0.25
448 GNUNET_CONFIGURATION_set_value_number (setu_cfg, "BOUNDARIES",
449 "UPPER_ELEMENT", 5000);
450
451
452 if (GNUNET_OK != GNUNET_CONFIGURATION_write (setu_cfg, "perf_setu.conf"))
453 GNUNET_log (
454 GNUNET_ERROR_TYPE_ERROR,
455 _ ("Failed to write subsystem default identifier map'.\n"));
456 run_petf_thread (100);
457 }
458
459 }
460 return;
461}
462
463
464int
465main (int argc, char **argv)
466{
467
468 GNUNET_log_setup ("perf_setu_api",
469 "WARNING",
470 NULL);
471 execute_perf ();
472 return 0;
473}