2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file ats/perf_ats_solver.c
22 * @brief generic performance test for ATS solvers
23 * @author Christian Grothoff
24 * @author Matthias Wachs
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet-service-ats_normalization.h"
31 #include "gnunet_ats_service.h"
32 #include "gnunet_ats_plugin.h"
33 #include "test_ats_api_common.h"
35 #define DEFAULT_PEERS_START 1
36 #define DEFAULT_PEERS_END 1
37 #define DEFAULT_ADDRESSES 1
38 #define DEFAULT_ATS_COUNT 2
41 * Handle for ATS address component
45 struct PerfPeer *peers;
48 * #peers to start benchmarking with
53 * #peers to end benchmarking with
58 * #addresses to benchmarking with
64 int opt_update_percent;
65 int opt_update_quantity;
72 struct GNUNET_STATISTICS_Handle *stat;
75 * A multihashmap to store all addresses
77 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
81 * Configured ATS solver
91 * Address suggestion requests DLL head
93 struct GAS_Addresses_Suggestion_Requests *r_head;
96 * Address suggestion requests DLL tail
98 struct GAS_Addresses_Suggestion_Requests *r_tail;
100 /* Solver functions */
101 struct GNUNET_ATS_PluginEnvironment env;
108 struct GNUNET_PeerIdentity id;
110 struct ATS_Address *head;
111 struct ATS_Address *tail;
114 static struct PerfHandle ph;
125 //static struct GNUNET_ATS_Information ats[2];
133 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
137 if (NULL != addresses)
139 GNUNET_CONTAINER_multihashmap_iterate (addresses, &addr_it, NULL);
140 GNUNET_CONTAINER_multihashmap_destroy (addresses);
143 if (NULL != ph.peers)
145 GNUNET_free(ph.peers);
148 GAS_normalization_stop ();
154 perf_create_peer (int cp)
157 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
158 &ph.peers[cp].id, sizeof (struct GNUNET_PeerIdentity));
159 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
160 GNUNET_i2s (&ph.peers[cp].id));
166 update_single_addresses (struct ATS_Address *cur)
171 r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
175 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
176 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
177 "Updating peer `%s' address %p type %s val %u\n",
178 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DELAY", r_val);
179 ph.env.sf.s_address_update_property (ph.solver, cur,
180 GNUNET_ATS_QUALITY_NET_DELAY,
181 r_val, (double) (100 + r_val / 100));
184 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
186 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
187 "Updating peer `%s' address %p type %s val %u\n",
188 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE", r_val);
189 ph.env.sf.s_address_update_property (ph.solver, cur,
190 GNUNET_ATS_QUALITY_NET_DISTANCE,
191 r_val, (double) (100 + r_val) / 100);
196 ph.env.sf.s_address_update_inuse (ph.solver, cur, GNUNET_YES);
202 bandwidth_changed_cb (void *cls, struct ATS_Address *address)
208 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
210 return GAS_normalization_get_preferences (id);
215 get_property_cb (void *cls, const struct ATS_Address *address)
217 return GAS_normalization_get_properties ((struct ATS_Address *) address);
221 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
222 uint32_t type, double prop_rel)
228 address_initial_update (void *solver,
229 struct GNUNET_CONTAINER_MultiPeerMap * addresses,
230 struct ATS_Address *address)
232 ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DELAY,
234 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
237 ph.env.sf.s_address_update_property (solver, address,
238 GNUNET_ATS_QUALITY_NET_DISTANCE, 10,
239 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
244 update_addresses (unsigned int cp, unsigned int ca, unsigned int up_q)
246 struct ATS_Address *cur;
252 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
253 "Updating addresses %u addresses per peer \n", up_q);
256 for (c_peer = 0; c_peer < cp; c_peer++)
258 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s'\n",
259 GNUNET_i2s (&ph.peers[c_peer].id));
260 for (c_select = 0; c_select < ca; c_select++)
263 while (c_select < ph.opt_update_quantity)
265 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
274 for (cur = ph.peers[c_peer].head; NULL != cur; cur = cur->next)
277 update_single_addresses (cur);
284 static struct ATS_Address *
285 perf_create_address (int cp, int ca)
287 struct ATS_Address *a;
288 a = create_address (&ph.peers[cp].id, "Test 1", "test 1", strlen ("test 1") + 1,
290 GNUNET_CONTAINER_DLL_insert(ph.peers[cp].head, ph.peers[cp].tail, a);
291 GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
292 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
299 struct ATS_Address *cur;
300 struct ATS_Address *next;
303 int count_p = ph.N_peers_end;
304 int count_a = ph.N_address;
306 struct ATS_Address * cur_addr;
307 ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer));
309 for (cp = 0; cp < count_p; cp++)
310 perf_create_peer (cp);
311 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
312 "Added %u peers\n", cp);
314 /* Set initial bulk start to not solve */
315 ph.env.sf.s_bulk_start (ph.solver);
316 bulk_running = GNUNET_YES;
318 for (cp = 0; cp < count_p; cp++)
320 for (ca = 0; ca < count_a; ca++)
322 cur_addr = perf_create_address (cp, ca);
324 ph.env.sf.s_add (ph.solver, cur_addr, GNUNET_ATS_NET_LAN);
325 address_initial_update (ph.solver, ph.addresses, cur_addr);
326 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
327 "Adding address for peer %u address %u\n", cp, ca);
329 ph.env.sf.s_get (ph.solver, &ph.peers[cp].id);
331 if (cp + 1 >= ph.N_peers_start)
333 /* Disable bulk to solve the problem */
334 if (GNUNET_YES == bulk_running)
336 ph.env.sf.s_bulk_stop (ph.solver);
337 bulk_running = GNUNET_NO;
340 /* Problem should be solved here */
342 /* Disable bulk to solve the problem */
343 if (GNUNET_NO == bulk_running)
345 ph.env.sf.s_bulk_start (ph.solver);
346 bulk_running = GNUNET_YES;
350 if ((0 < ph.opt_update_quantity) || (0 < ph.opt_update_percent))
353 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
354 "Updating problem with %u peers and %u addresses\n", cp + 1, ca);
355 //ph.env.sf.s_bulk_start (ph.solver);
356 //update_addresses (cp + 1, ca, ph.opt_update_quantity);
357 //ph.env.sf.s_bulk_stop (ph.solver);
362 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
363 "Done, cleaning up addresses\n");
364 for (cp = 0; cp < count_p; cp++)
366 for (cur = ph.peers[cp].head; cur != NULL ; cur = next)
368 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
369 "Deleting addresses for peer %u\n", cp);
370 ph.env.sf.s_del (ph.solver, cur, GNUNET_NO);
372 GNUNET_CONTAINER_DLL_remove(ph.peers[cp].head, ph.peers[cp].tail, cur);
377 GNUNET_free(ph.peers);
382 run (void *cls, char * const *args, const char *cfgfile,
383 const struct GNUNET_CONFIGURATION_Handle *cfg)
385 GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
387 char *src_filename = GNUNET_strdup (__FILE__);
388 char *test_filename = cls;
391 unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
392 unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
395 /* Extract test name */
396 if (NULL == (sep = (strstr (src_filename,".c"))))
404 if (NULL != (sep = strstr (test_filename, ".exe")))
407 if (NULL == (solver = strstr (test_filename, src_filename)))
413 solver += strlen (src_filename) +1;
415 if (0 == strcmp(solver, "proportional"))
417 ph.ats_mode = MODE_PROPORTIONAL;
418 ph.ats_string = "proportional";
420 else if (0 == strcmp(solver, "mlp"))
422 ph.ats_mode = MODE_MLP;
423 ph.ats_string = "mlp";
425 else if ((0 == strcmp(solver, "ril")))
427 ph.ats_mode = MODE_RIL;
428 ph.ats_string = "ril";
432 GNUNET_free (src_filename);
437 GNUNET_free (src_filename);
439 /* Calculcate peers */
440 if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
442 ph.N_peers_start = DEFAULT_PEERS_START;
443 ph.N_peers_end = DEFAULT_PEERS_END;
445 if (0 == ph.N_address)
446 ph.N_address = DEFAULT_ADDRESSES;
448 if (ph.opt_update_quantity > ph.N_address)
451 _("Trying to update more addresses than we have per peer! (%u vs %u)"),
452 ph.opt_update_quantity, ph.N_address);
456 if (ph.N_peers_start != ph.N_peers_end)
457 fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses\n",
458 ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address);
460 fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses\n",
461 ph.ats_string, ph.N_peers_end, ph.N_address);
464 if (GNUNET_ATS_NetworkTypeCount != load_quotas (cfg,
465 quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
474 ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
475 ph.env.stats = ph.stat;
476 ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
477 ph.env.addresses = ph.addresses;
478 ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
479 ph.env.get_preferences = &get_preferences_cb;
480 ph.env.get_property = &get_property_cb;
481 ph.env.network_count = GNUNET_ATS_NetworkTypeCount;
482 int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
483 for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
485 ph.env.networks[c] = networks[c];
486 ph.env.out_quota[c] = quotas_out[c];
487 ph.env.in_quota[c] = quotas_in[c];
488 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading network quotas: `%s' %llu %llu \n",
489 GNUNET_ATS_print_network_type(ph.env.networks[c]),
493 GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
495 GNUNET_asprintf (&plugin, "libgnunet_plugin_ats_%s", ph.ats_string);
496 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s'\n"), ph.ats_string);
497 if (NULL == (ph.solver = GNUNET_PLUGIN_load (plugin, &ph.env)))
499 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), plugin);
508 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Unloading solver `%s'\n"), ph.ats_string);
509 GNUNET_PLUGIN_unload (plugin, ph.solver);
510 GNUNET_free (plugin);
515 main (int argc, char *argv[])
517 /* extract command line arguments */
518 ph.opt_dump = GNUNET_NO;
519 ph.opt_update_quantity = 0;
520 ph.opt_update_percent = 0;
521 ph.N_peers_start = 0;
524 ph.ats_string = NULL;
526 static struct GNUNET_GETOPT_CommandLineOption options[] = {
527 { 'a', "addresses", NULL,
528 gettext_noop ("addresses to use"),
529 1, &GNUNET_GETOPT_set_uint, &ph.N_address },
530 { 's', "start", NULL,
531 gettext_noop ("start with peer"),
532 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_start },
534 gettext_noop ("end with peer"),
535 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_end },
536 { 'p', "percentage", NULL,
537 gettext_noop ("update a fix percentage of addresses"),
538 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_percent },
539 { 'q', "quantity", NULL,
540 gettext_noop ("update a fix quantity of addresses"),
541 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_quantity },
542 GNUNET_GETOPT_OPTION_END
545 GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
550 /* end of file perf_ats_solver.c */