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 10
36 #define DEFAULT_PEERS_END 10
37 #define DEFAULT_ADDRESSES 10
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;
74 struct GNUNET_STATISTICS_Handle *stat;
77 * A multihashmap to store all addresses
79 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
83 * Configured ATS solver
93 * Address suggestion requests DLL head
95 struct GAS_Addresses_Suggestion_Requests *r_head;
98 * Address suggestion requests DLL tail
100 struct GAS_Addresses_Suggestion_Requests *r_tail;
102 /* Solver functions */
103 struct GNUNET_ATS_PluginEnvironment env;
110 struct GNUNET_PeerIdentity id;
112 struct ATS_Address *head;
113 struct ATS_Address *tail;
116 static struct PerfHandle ph;
127 //static struct GNUNET_ATS_Information ats[2];
135 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
139 if (NULL != addresses)
141 GNUNET_CONTAINER_multihashmap_iterate (addresses, &addr_it, NULL);
142 GNUNET_CONTAINER_multihashmap_destroy (addresses);
145 if (NULL != ph.peers)
147 GNUNET_free(ph.peers);
150 GAS_normalization_stop ();
156 perf_create_peer (int cp)
159 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
160 &ph.peers[cp].id, sizeof (struct GNUNET_PeerIdentity));
161 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
162 GNUNET_i2s (&ph.peers[cp].id));
168 perf_update_address (struct ATS_Address *cur)
173 r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
177 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
178 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
179 "Updating peer `%s' address %p type %s val %u\n",
180 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DELAY", r_val);
181 ph.env.sf.s_address_update_property (ph.solver, cur,
182 GNUNET_ATS_QUALITY_NET_DELAY,
183 r_val, (double) (100 + r_val / 100));
186 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
188 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
189 "Updating peer `%s' address %p type %s val %u\n",
190 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE", r_val);
191 ph.env.sf.s_address_update_property (ph.solver, cur,
192 GNUNET_ATS_QUALITY_NET_DISTANCE,
193 r_val, (double) (100 + r_val) / 100);
198 ph.env.sf.s_address_update_inuse (ph.solver, cur, GNUNET_YES);
204 bandwidth_changed_cb (void *cls, struct ATS_Address *address)
206 if (0 == ntohl(address->assigned_bw_out.value__) &&
207 0 == ntohl(address->assigned_bw_in.value__))
210 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
211 "Bandwidth changed addresses %s %p to %llu Bps out / %llu Bps in\n",
212 GNUNET_i2s (&address->peer),
214 ntohl(address->assigned_bw_out.value__),
215 ntohl(address->assigned_bw_in.value__));
216 if (GNUNET_YES == ph.bulk_running)
222 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
224 return GAS_normalization_get_preferences (id);
229 get_property_cb (void *cls, const struct ATS_Address *address)
231 return GAS_normalization_get_properties ((struct ATS_Address *) address);
235 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
236 uint32_t type, double prop_rel)
242 perf_address_initial_update (void *solver,
243 struct GNUNET_CONTAINER_MultiPeerMap * addresses,
244 struct ATS_Address *address)
246 ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DELAY,
248 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
251 ph.env.sf.s_address_update_property (solver, address,
252 GNUNET_ATS_QUALITY_NET_DISTANCE, 10,
253 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
258 perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int up_q)
260 struct ATS_Address *cur;
266 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
267 "Updating addresses %u addresses per peer \n", up_q);
270 for (c_peer = 0; c_peer < cp; c_peer++)
272 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s'\n",
273 GNUNET_i2s (&ph.peers[c_peer].id));
274 for (c_select = 0; c_select < ca; c_select++)
277 while (c_select < ph.opt_update_quantity)
279 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
288 for (cur = ph.peers[c_peer].head; NULL != cur; cur = cur->next)
291 perf_update_address (cur);
298 static struct ATS_Address *
299 perf_create_address (int cp, int ca)
301 struct ATS_Address *a;
302 a = create_address (&ph.peers[cp].id,
303 "Test 1", "test 1", strlen ("test 1") + 1, 0);
304 GNUNET_CONTAINER_DLL_insert (ph.peers[cp].head, ph.peers[cp].tail, a);
305 GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
306 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
313 struct ATS_Address *cur;
314 struct ATS_Address *next;
317 int count_p = ph.N_peers_end;
318 int count_a = ph.N_address;
319 struct ATS_Address * cur_addr;
320 struct GNUNET_TIME_Absolute start;
321 struct GNUNET_TIME_Absolute end;
322 struct GNUNET_TIME_Relative delta;
324 ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer));
326 for (cp = 0; cp < count_p; cp++)
327 perf_create_peer (cp);
328 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
329 "Added %u peers\n", cp);
331 /* Set initial bulk start to not solve */
332 ph.env.sf.s_bulk_start (ph.solver);
333 ph.bulk_running = GNUNET_YES;
335 for (cp = 0; cp < count_p; cp++)
337 for (ca = 0; ca < count_a; ca++)
339 cur_addr = perf_create_address (cp, ca);
341 ph.env.sf.s_add (ph.solver, cur_addr, GNUNET_ATS_NET_LAN);
342 perf_address_initial_update (ph.solver, ph.addresses, cur_addr);
343 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
344 "Adding address for peer %u address %u\n", cp, ca);
346 /* Notify solver about request */
347 ph.env.sf.s_get (ph.solver, &ph.peers[cp].id);
349 if (cp + 1 >= ph.N_peers_start)
351 /* Disable bulk to solve the problem */
352 if (GNUNET_YES == ph.bulk_running)
354 start = GNUNET_TIME_absolute_get();
355 ph.bulk_running = GNUNET_NO;
356 ph.env.sf.s_bulk_stop (ph.solver);
363 /* Problem is solved by the solver here due to unlocking */
365 /* Disable bulk to solve the problem */
366 if (GNUNET_NO == ph.bulk_running)
369 end = GNUNET_TIME_absolute_get();
370 delta = GNUNET_TIME_absolute_get_difference(start, end);
371 fprintf (stderr, "Solver took %llu us to solve problem with %u peers and %u addresses per peer\n",
372 (unsigned long long) delta.rel_value_us,
374 ph.env.sf.s_bulk_start (ph.solver);
375 ph.bulk_running = GNUNET_YES;
378 if ((0 < ph.opt_update_quantity) || (0 < ph.opt_update_percent))
381 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
382 "Updating problem with %u peers and %u addresses\n", cp + 1, ca);
383 //ph.env.sf.s_bulk_start (ph.solver);
384 //update_addresses (cp + 1, ca, ph.opt_update_quantity);
385 //ph.env.sf.s_bulk_stop (ph.solver);
390 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
391 "Done, cleaning up addresses\n");
392 if (GNUNET_NO == ph.bulk_running)
394 ph.env.sf.s_bulk_start (ph.solver);
395 ph.bulk_running = GNUNET_YES;
398 for (cp = 0; cp < count_p; cp++)
400 for (cur = ph.peers[cp].head; cur != NULL ; cur = next)
402 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
403 "Deleting addresses for peer %u\n", cp);
404 GNUNET_CONTAINER_multipeermap_remove (ph.addresses, &ph.peers[cp].id, cur);
405 ph.env.sf.s_del (ph.solver, cur, GNUNET_NO);
407 GNUNET_CONTAINER_DLL_remove(ph.peers[cp].head, ph.peers[cp].tail, cur);
412 GNUNET_free(ph.peers);
417 run (void *cls, char * const *args, const char *cfgfile,
418 const struct GNUNET_CONFIGURATION_Handle *cfg)
420 GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
422 char *src_filename = GNUNET_strdup (__FILE__);
423 char *test_filename = cls;
426 unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
427 unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
430 /* Extract test name */
431 if (NULL == (sep = (strstr (src_filename,".c"))))
439 if (NULL != (sep = strstr (test_filename, ".exe")))
442 if (NULL == (solver = strstr (test_filename, src_filename)))
448 solver += strlen (src_filename) +1;
450 if (0 == strcmp(solver, "proportional"))
452 ph.ats_mode = MODE_PROPORTIONAL;
453 ph.ats_string = "proportional";
455 else if (0 == strcmp(solver, "mlp"))
457 ph.ats_mode = MODE_MLP;
458 ph.ats_string = "mlp";
460 else if ((0 == strcmp(solver, "ril")))
462 ph.ats_mode = MODE_RIL;
463 ph.ats_string = "ril";
467 GNUNET_free (src_filename);
472 GNUNET_free (src_filename);
474 /* Calculcate peers */
475 if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
477 ph.N_peers_start = DEFAULT_PEERS_START;
478 ph.N_peers_end = DEFAULT_PEERS_END;
480 if (0 == ph.N_address)
481 ph.N_address = DEFAULT_ADDRESSES;
483 if (ph.opt_update_quantity > ph.N_address)
486 _("Trying to update more addresses than we have per peer! (%u vs %u)"),
487 ph.opt_update_quantity, ph.N_address);
491 if (ph.N_peers_start != ph.N_peers_end)
492 fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses\n",
493 ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address);
495 fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses\n",
496 ph.ats_string, ph.N_peers_end, ph.N_address);
499 if (GNUNET_ATS_NetworkTypeCount != load_quotas (cfg,
500 quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
509 ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
510 ph.env.stats = ph.stat;
511 ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
512 ph.env.addresses = ph.addresses;
513 ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
514 ph.env.get_preferences = &get_preferences_cb;
515 ph.env.get_property = &get_property_cb;
516 ph.env.network_count = GNUNET_ATS_NetworkTypeCount;
517 int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
518 for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
520 ph.env.networks[c] = networks[c];
521 ph.env.out_quota[c] = quotas_out[c];
522 ph.env.in_quota[c] = quotas_in[c];
523 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading network quotas: `%s' %llu %llu \n",
524 GNUNET_ATS_print_network_type(ph.env.networks[c]),
528 GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
530 GNUNET_asprintf (&plugin, "libgnunet_plugin_ats_%s", ph.ats_string);
531 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s'\n"), ph.ats_string);
532 if (NULL == (ph.solver = GNUNET_PLUGIN_load (plugin, &ph.env)))
534 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), plugin);
543 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Unloading solver `%s'\n"), ph.ats_string);
544 GNUNET_PLUGIN_unload (plugin, ph.solver);
545 GNUNET_free (plugin);
550 main (int argc, char *argv[])
552 /* extract command line arguments */
553 ph.opt_dump = GNUNET_NO;
554 ph.opt_update_quantity = 0;
555 ph.opt_update_percent = 0;
556 ph.N_peers_start = 0;
559 ph.ats_string = NULL;
561 static struct GNUNET_GETOPT_CommandLineOption options[] = {
562 { 'a', "addresses", NULL,
563 gettext_noop ("addresses to use"),
564 1, &GNUNET_GETOPT_set_uint, &ph.N_address },
565 { 's', "start", NULL,
566 gettext_noop ("start with peer"),
567 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_start },
569 gettext_noop ("end with peer"),
570 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_end },
571 { 'p', "percentage", NULL,
572 gettext_noop ("update a fix percentage of addresses"),
573 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_percent },
574 { 'q', "quantity", NULL,
575 gettext_noop ("update a fix quantity of addresses"),
576 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_quantity },
577 GNUNET_GETOPT_OPTION_END
580 GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
585 /* end of file perf_ats_solver.c */