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_UPDATE_PERCENTAGE 20
36 #define DEFAULT_PEERS_START 10
37 #define DEFAULT_PEERS_END 10
38 #define DEFAULT_ADDRESSES 10
39 #define DEFAULT_ATS_COUNT 2
41 #define GNUPLOT_PROP_TEMPLATE "#!/usr/bin/gnuplot \n" \
42 "set datafile separator ';' \n" \
43 "set title \"Execution time Proportional solver \" \n" \
44 "set xlabel \"Number of peers\" \n" \
45 "set ylabel \"Execution time in us\" \n" \
48 #define GNUPLOT_PROP_UPDATE_TEMPLATE "#!/usr/bin/gnuplot \n" \
49 "set datafile separator ';' \n" \
50 "set title \"Execution time Proportional solver with updated problem\" \n" \
51 "set xlabel \"Number of peers\" \n" \
52 "set ylabel \"Execution time in us\" \n" \
55 #define GNUPLOT_MLP_TEMPLATE "#!/usr/bin/gnuplot \n" \
56 "set datafile separator ';' \n" \
57 "set title \"Execution time MLP solver \" \n" \
58 "set xlabel \"Number of peers\" \n" \
59 "set ylabel \"Execution time in us\" \n" \
62 #define GNUPLOT_MLP_UPDATE_TEMPLATE "#!/usr/bin/gnuplot \n" \
63 "set datafile separator ';' \n" \
64 "set title \"Execution time MLP solver with updated problem\" \n" \
65 "set xlabel \"Number of peers\" \n" \
66 "set ylabel \"Execution time in us\" \n" \
69 #define GNUPLOT_RIL_TEMPLATE "#!/usr/bin/gnuplot \n" \
70 "set datafile separator ';' \n" \
71 "set title \"Execution time RIL solver \" \n" \
72 "set xlabel \"Number of peers\" \n" \
73 "set ylabel \"Execution time in us\" \n" \
76 #define GNUPLOT_RIL_UPDATE_TEMPLATE "#!/usr/bin/gnuplot \n" \
77 "set datafile separator ';' \n" \
78 "set title \"Execution time RIL solver with updated problem\" \n" \
79 "set xlabel \"Number of peers\" \n" \
80 "set ylabel \"Execution time in us\" \n" \
84 * Handle for ATS address component
91 struct PerfPeer *peers;
101 struct GNUNET_STATISTICS_Handle *stat;
104 * A multihashmap to store all addresses
106 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
111 struct GNUNET_ATS_PluginEnvironment env;
113 struct Iteration *iterations_results;
115 struct Result *current_result;
121 * Solver description as string
126 * Configured ATS solver
131 * #peers to start benchmarking with
136 * #peers to end benchmarking with
141 * #addresses to benchmarking with
146 * Percentage of peers to update
148 int opt_update_percent;
151 * Create gnuplot file
161 * Number of iterations
168 int current_iteration;
171 * Is a bulk operation running?
176 * Is a bulk operation running?
178 int expecting_solution;
183 struct Result *result_head;
185 struct Result *result_tail;
197 enum GAS_Solver_Additional_Information info;
199 struct GNUNET_TIME_Relative d_setup;
200 struct GNUNET_TIME_Relative d_lp;
201 struct GNUNET_TIME_Relative d_mlp;
202 struct GNUNET_TIME_Relative d_total;
204 struct GNUNET_TIME_Absolute s_setup;
205 struct GNUNET_TIME_Absolute s_lp;
206 struct GNUNET_TIME_Absolute s_mlp;
207 struct GNUNET_TIME_Absolute s_total;
209 struct GNUNET_TIME_Absolute e_setup;
210 struct GNUNET_TIME_Absolute e_lp;
211 struct GNUNET_TIME_Absolute e_mlp;
212 struct GNUNET_TIME_Absolute e_total;
217 struct GNUNET_PeerIdentity id;
219 struct ATS_Address *head;
220 struct ATS_Address *tail;
223 static struct PerfHandle ph;
234 //static struct GNUNET_ATS_Information ats[2];
242 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
246 if (NULL != addresses)
248 GNUNET_CONTAINER_multihashmap_iterate (addresses, &addr_it, NULL);
249 GNUNET_CONTAINER_multihashmap_destroy (addresses);
252 if (NULL != ph.peers)
254 GNUNET_free(ph.peers);
257 GAS_normalization_stop ();
263 perf_create_peer (int cp)
266 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
267 &ph.peers[cp].id, sizeof (struct GNUNET_PeerIdentity));
268 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
269 GNUNET_i2s (&ph.peers[cp].id));
275 perf_update_address (struct ATS_Address *cur)
280 r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
284 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
285 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
286 "Updating peer `%s' address %p type %s val %u\n",
287 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DELAY", r_val);
288 ph.env.sf.s_address_update_property (ph.solver, cur,
289 GNUNET_ATS_QUALITY_NET_DELAY,
290 r_val, (double) (100 + r_val / 100));
293 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
295 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
296 "Updating peer `%s' address %p type %s val %u\n",
297 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE", r_val);
298 ph.env.sf.s_address_update_property (ph.solver, cur,
299 GNUNET_ATS_QUALITY_NET_DISTANCE,
300 r_val, (double) (100 + r_val) / 100);
305 ph.env.sf.s_address_update_inuse (ph.solver, cur, GNUNET_YES);
310 bandwidth_changed_cb (void *cls,
311 struct ATS_Address *address)
313 if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
314 (0 == ntohl (address->assigned_bw_in.value__)) )
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
318 "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
319 GNUNET_i2s (&address->peer),
321 (unsigned int) ntohl (address->assigned_bw_out.value__),
322 (unsigned int) ntohl (address->assigned_bw_in.value__));
323 if (GNUNET_YES == ph.bulk_running)
330 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
332 return GAS_normalization_get_preferences_by_peer (id);
337 get_property_cb (void *cls, const struct ATS_Address *address)
339 return GAS_normalization_get_properties ((struct ATS_Address *) address);
343 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
344 uint32_t type, double prop_rel)
350 perf_address_initial_update (void *solver,
351 struct GNUNET_CONTAINER_MultiPeerMap * addresses,
352 struct ATS_Address *address)
354 ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DELAY,
356 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
359 ph.env.sf.s_address_update_property (solver, address,
360 GNUNET_ATS_QUALITY_NET_DISTANCE, 10,
361 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
366 perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int percentage_peers)
368 struct ATS_Address *cur_address;
377 count = cp * ((double) percentage_peers / 100);
378 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
379 "Updating %u of %u peers \n", count, cp);
381 for (c_peer = 0; c_peer < cp; c_peer++)
386 while (c_select < count)
388 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp);
392 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
393 "Updating peer [%u] \n", r);
397 for (c_cur_p = 0; c_cur_p < cp; c_cur_p++)
401 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
402 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
403 "Updating peer [%u] address [%u]\n", c_cur_p, r);
406 for (cur_address = ph.peers[c_cur_p].head; NULL != cur_address; cur_address = cur_address->next)
409 perf_update_address (cur_address);
418 static struct ATS_Address *
419 perf_create_address (int cp, int ca)
421 struct ATS_Address *a;
422 a = create_address (&ph.peers[cp].id,
423 "Test 1", "test 1", strlen ("test 1") + 1, 0);
424 GNUNET_CONTAINER_DLL_insert (ph.peers[cp].head, ph.peers[cp].tail, a);
425 GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
426 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
431 solver_info_cb (void *cls,
432 enum GAS_Solver_Operation op,
433 enum GAS_Solver_Status stat,
434 enum GAS_Solver_Additional_Information add)
439 add_info = "GAS_INFO_NONE";
442 add_info = "GAS_INFO_MLP_FULL";
444 case GAS_INFO_UPDATED:
445 add_info = "GAS_INFO_MLP_UPDATED";
447 case GAS_INFO_PROP_ALL:
448 add_info = "GAS_INFO_PROP_ALL";
450 case GAS_INFO_PROP_SINGLE:
451 add_info = "GAS_INFO_PROP_SINGLE";
454 add_info = "INVALID";
461 case GAS_OP_SOLVE_START:
462 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
463 "Solver notifies `%s' with result `%s' `%s' in iteration %u \n", "GAS_OP_SOLVE_START",
464 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info, ph.current_iteration);
465 if (GNUNET_NO == ph.expecting_solution)
467 /* We do not expect a solution at the moment */
472 if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result))
474 /* Create new result */
475 tmp = GNUNET_new (struct Result);
476 ph.current_result = tmp;
477 GNUNET_CONTAINER_DLL_insert_tail(ph.iterations_results[ph.current_iteration-1].result_head,
478 ph.iterations_results[ph.current_iteration-1].result_tail, tmp);
479 ph.current_result->addresses = ph.current_a;
480 ph.current_result->peers = ph.current_p;
481 ph.current_result->s_total = GNUNET_TIME_absolute_get();
482 ph.current_result->d_total = GNUNET_TIME_UNIT_FOREVER_REL;
483 ph.current_result->d_setup = GNUNET_TIME_UNIT_FOREVER_REL;
484 ph.current_result->d_lp = GNUNET_TIME_UNIT_FOREVER_REL;
485 ph.current_result->d_mlp = GNUNET_TIME_UNIT_FOREVER_REL;
486 ph.current_result->info = add;
487 if (add == GAS_INFO_UPDATED)
488 ph.current_result->update = GNUNET_YES;
490 ph.current_result->update = GNUNET_NO;
493 case GAS_OP_SOLVE_STOP:
494 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
495 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
496 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
497 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
499 /* We do not expect a solution at the moment */
503 if (NULL != ph.current_result)
505 /* Finalize result */
506 ph.current_result->e_total = GNUNET_TIME_absolute_get ();
507 ph.current_result->d_total = GNUNET_TIME_absolute_get_difference (
508 ph.current_result->s_total, ph.current_result->e_total);
510 ph.current_result = NULL;
513 case GAS_OP_SOLVE_SETUP_START:
514 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
515 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
516 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
517 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
522 ph.current_result->s_setup = GNUNET_TIME_absolute_get ();
525 case GAS_OP_SOLVE_SETUP_STOP:
526 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
527 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
528 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
529 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
534 ph.current_result->e_setup = GNUNET_TIME_absolute_get ();
535 ph.current_result->d_setup = GNUNET_TIME_absolute_get_difference (
536 ph.current_result->s_setup, ph.current_result->e_setup);
539 case GAS_OP_SOLVE_MLP_LP_START:
540 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
541 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
542 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
543 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
548 ph.current_result->s_lp = GNUNET_TIME_absolute_get ();
550 case GAS_OP_SOLVE_MLP_LP_STOP:
551 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
552 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
553 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
554 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
559 ph.current_result->e_lp = GNUNET_TIME_absolute_get ();
560 ph.current_result->d_lp = GNUNET_TIME_absolute_get_difference (
561 ph.current_result->s_lp, ph.current_result->e_lp);
564 case GAS_OP_SOLVE_MLP_MLP_START:
565 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
566 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
567 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
568 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
573 ph.current_result->s_mlp = GNUNET_TIME_absolute_get ();
575 case GAS_OP_SOLVE_MLP_MLP_STOP:
576 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
577 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
578 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
579 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
584 ph.current_result->e_mlp = GNUNET_TIME_absolute_get ();
585 ph.current_result->d_mlp = GNUNET_TIME_absolute_get_difference (
586 ph.current_result->s_mlp, ph.current_result->e_mlp);
588 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
589 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
590 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
591 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
593 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
594 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
595 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
596 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
604 write_gnuplot_script (char * data_fn, int full)
606 struct GNUNET_DISK_FileHandle *f;
612 switch (ph.ats_mode) {
613 case MODE_PROPORTIONAL:
614 if (GNUNET_YES == full)
615 template = GNUPLOT_PROP_TEMPLATE;
617 template = GNUPLOT_PROP_UPDATE_TEMPLATE;
620 if (GNUNET_YES == full)
621 template = GNUPLOT_MLP_TEMPLATE;
623 template = GNUPLOT_MLP_UPDATE_TEMPLATE;
626 if (GNUNET_YES == full)
627 template = GNUPLOT_RIL_TEMPLATE;
629 template = GNUPLOT_RIL_UPDATE_TEMPLATE;
636 if (GNUNET_YES == full)
637 GNUNET_asprintf (&gfn, "perf_%s_full_%u_%u_%u.gnuplot", ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address);
639 GNUNET_asprintf (&gfn, "perf_%s_update_%u_%u_%u.gnuplot", ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address);
641 f = GNUNET_DISK_file_open (gfn,
642 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
643 GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
646 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn);
651 if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, template, strlen(template)))
652 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn);
655 if (MODE_PROPORTIONAL == ph.ats_mode)
657 GNUNET_asprintf (&data, "plot '%s' using 1:%u with lines title 'Total time to solve'\n" \
661 else if (MODE_MLP == ph.ats_mode)
663 GNUNET_asprintf (&data, "plot '%s' using 1:%u with lines title 'Total time to solve',\\\n" \
664 "'%s' using 1:%u with lines title 'Time to setup',\\\n"
665 "'%s' using 1:%u with lines title 'Time to solve LP',\\\n"
666 "'%s' using 1:%u with lines title 'Total time to solve MLP'\n" \
673 else if (MODE_RIL == ph.ats_mode)
675 GNUNET_asprintf (&data,
676 "plot '%s' using 1:%u with lines title 'Total time to solve'\n" \
681 if ((NULL != data) &&
682 (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen(data))))
683 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
684 "Cannot write data to plot file `%s'\n",
686 GNUNET_free_non_null (data);
688 if (GNUNET_SYSERR == GNUNET_DISK_file_close(f))
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Cannot close gnuplot file `%s'\n",
693 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
694 "Data successfully written to plot file `%s'\n",
701 * Evaluate results for a specific iteration
703 * @oaram iteration the iteration to evaluate
707 evaluate (int iteration)
709 struct GNUNET_DISK_FileHandle *f_full;
710 struct GNUNET_DISK_FileHandle *f_update;
712 char * data_fn_update;
728 GNUNET_asprintf (&data_fn_full,
729 "perf_%s_full_%u_%u_%u.data",
734 f_full = GNUNET_DISK_file_open (data_fn_full,
735 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
736 GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
740 "Cannot open gnuplot file `%s'\n",
742 GNUNET_free (data_fn_full);
745 data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
746 if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_full, data, strlen(data)))
747 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
748 "Cannot write data to log file `%s'\n",
750 write_gnuplot_script (data_fn_full, GNUNET_YES);
753 data_fn_update = NULL;
754 if ((ph.create_plot) && (GNUNET_YES == ph.measure_updates))
756 GNUNET_asprintf (&data_fn_update, "perf_%s_update_%u_%u_%u.data", ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address);
757 f_update = GNUNET_DISK_file_open (data_fn_update,
758 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
759 GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
760 if (NULL == f_update)
762 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
763 "Cannot open gnuplot file `%s'\n", data_fn_update);
764 GNUNET_free (data_fn_update);
766 GNUNET_DISK_file_close (f_full);
767 GNUNET_free (data_fn_full);
770 data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
771 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data)))
772 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
773 "Cannot write data to log file `%s'\n",
775 write_gnuplot_script (data_fn_update, GNUNET_NO);
779 next = ph.iterations_results[ph.current_iteration -1].result_head;
780 while (NULL != (cur = next))
789 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_total.rel_value_us)
792 "Total time to solve %s for %u peers %u addresses: %llu us\n",
793 (GNUNET_YES == cur->update) ? "updated" : "full",
794 cur->peers, cur->addresses, (unsigned long long) cur->d_total.rel_value_us);
795 GNUNET_asprintf(&str_d_total,
797 (unsigned long long) cur->d_total.rel_value_us);
800 GNUNET_asprintf(&str_d_total, "-1");
801 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_setup.rel_value_us)
803 fprintf (stderr, "Total time to setup %s %u peers %u addresses: %llu us\n",
804 (GNUNET_YES == cur->update) ? "updated" : "full",
805 cur->peers, cur->addresses, (unsigned long long )cur->d_setup.rel_value_us);
806 GNUNET_asprintf(&str_d_setup, "%llu", (unsigned long long )cur->d_setup.rel_value_us);
809 GNUNET_asprintf(&str_d_setup, "-1");
810 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_lp.rel_value_us)
813 "Total time to solve %s LP for %u peers %u addresses: %llu us\n",
814 (GNUNET_YES == cur->update) ? "updated" : "full",
817 (unsigned long long )cur->d_lp.rel_value_us);
818 GNUNET_asprintf (&str_d_lp,
820 (unsigned long long )cur->d_lp.rel_value_us);
823 GNUNET_asprintf (&str_d_lp, "-1");
824 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_mlp.rel_value_us)
826 fprintf (stderr, "Total time to solve %s MLP for %u peers %u addresses: %llu us\n",
827 (GNUNET_YES == cur->update) ? "updated" : "full",
828 cur->peers, cur->addresses, (unsigned long long )cur->d_mlp.rel_value_us);
829 GNUNET_asprintf (&str_d_mlp,
831 (unsigned long long )cur->d_mlp.rel_value_us);
834 GNUNET_asprintf (&str_d_mlp, "-1");
837 if (GNUNET_YES == ph.create_plot)
840 GNUNET_asprintf (&data,
841 "%u;%u;%s;%s;%s;%s\n",
842 cur->peers, cur->addresses,
847 if (cur->update == GNUNET_NO)
849 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data, strlen(data)))
850 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
851 "Cannot write data to log file `%s'\n",
854 if ((cur->update == GNUNET_YES) && (NULL != f_update))
856 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data)))
857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
858 "Cannot write data to log file `%s'\n",
863 GNUNET_free_non_null (str_d_total);
864 GNUNET_free_non_null (str_d_setup);
865 GNUNET_free_non_null (str_d_lp);
866 GNUNET_free_non_null (str_d_mlp);
868 GNUNET_CONTAINER_DLL_remove (ph.iterations_results[ph.current_iteration-1].result_head,
869 ph.iterations_results[ph.current_iteration-1].result_tail, cur);
873 if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full)))
874 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
876 GNUNET_free_non_null (data_fn_full);
878 if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_update)))
879 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
881 GNUNET_free_non_null (data_fn_update);
888 struct ATS_Address *cur;
889 struct ATS_Address *next;
892 int count_p = ph.N_peers_end;
893 int count_a = ph.N_address;
894 struct ATS_Address * cur_addr;
897 ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer));
898 for (cp = 0; cp < count_p; cp++)
899 perf_create_peer (cp);
900 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
901 "Iteration %u of %u, added %u peers\n", ph.current_iteration, ph.iterations, cp);
903 for (cp = 0; cp < count_p; cp++)
905 if (GNUNET_NO == ph.bulk_running)
907 ph.bulk_running = GNUNET_YES;
908 ph.env.sf.s_bulk_start (ph.solver);
910 ph.current_p = cp + 1;
911 for (ca = 0; ca < count_a; ca++)
913 cur_addr = perf_create_address (cp, ca);
915 ph.env.sf.s_add (ph.solver, cur_addr, GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_ATS_NetworkTypeCount));
916 ph.current_a = ca + 1;
917 perf_address_initial_update (ph.solver, ph.addresses, cur_addr);
918 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
919 "Adding address for peer %u address %u\n", cp, ca);
921 /* Notify solver about request */
922 ph.env.sf.s_get (ph.solver, &ph.peers[cp].id);
924 if (cp + 1 >= ph.N_peers_start)
926 /* Disable bulk to solve the problem */
927 if (GNUNET_YES == ph.bulk_running)
929 ph.expecting_solution = GNUNET_YES;
930 ph.bulk_running = GNUNET_NO;
931 ph.env.sf.s_bulk_stop (ph.solver);
938 /* Problem is solved by the solver here due to unlocking */
939 ph.expecting_solution = GNUNET_NO;
941 /* Update the problem */
942 if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates))
945 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
946 "Updating problem with %u peers and %u addresses\n", cp + 1, ca);
948 ph.expecting_solution = GNUNET_YES;
949 if (GNUNET_NO == ph.bulk_running)
951 ph.bulk_running = GNUNET_YES;
952 ph.env.sf.s_bulk_start (ph.solver);
954 perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent);
955 ph.bulk_running = GNUNET_NO;
956 ph.env.sf.s_bulk_stop (ph.solver);
957 /* Problem is solved by the solver here due to unlocking */
958 ph.expecting_solution = GNUNET_NO;
960 GNUNET_assert (GNUNET_NO == ph.bulk_running);
964 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
965 "Done, cleaning up addresses\n");
966 if (GNUNET_NO == ph.bulk_running)
968 ph.env.sf.s_bulk_start (ph.solver);
969 ph.bulk_running = GNUNET_YES;
972 for (cp = 0; cp < count_p; cp++)
974 for (cur = ph.peers[cp].head; cur != NULL ; cur = next)
976 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
977 "Deleting addresses for peer %u\n", cp);
978 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (ph.addresses,
979 &ph.peers[cp].id, cur));
980 ph.env.sf.s_del (ph.solver, cur, GNUNET_NO);
982 GNUNET_CONTAINER_DLL_remove(ph.peers[cp].head, ph.peers[cp].tail, cur);
987 GNUNET_free(ph.peers);
992 run (void *cls, char * const *args, const char *cfgfile,
993 const struct GNUNET_CONFIGURATION_Handle *cfg)
995 GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
997 char *src_filename = GNUNET_strdup (__FILE__);
998 char *test_filename = cls;
1001 struct GNUNET_CONFIGURATION_Handle *solver_cfg;
1002 unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
1003 unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
1006 /* Extract test name */
1007 if (NULL == (sep = (strstr (src_filename,".c"))))
1009 GNUNET_free (src_filename);
1016 if (NULL != (sep = strstr (test_filename, ".exe")))
1019 if (NULL == (solver = strstr (test_filename, src_filename)))
1021 GNUNET_free (src_filename);
1026 solver += strlen (src_filename) +1;
1028 if (0 == strcmp(solver, "proportional"))
1030 ph.ats_mode = MODE_PROPORTIONAL;
1031 ph.ats_string = "proportional";
1033 else if (0 == strcmp(solver, "mlp"))
1035 ph.ats_mode = MODE_MLP;
1036 ph.ats_string = "mlp";
1038 else if ((0 == strcmp(solver, "ril")))
1040 ph.ats_mode = MODE_RIL;
1041 ph.ats_string = "ril";
1045 GNUNET_free (src_filename);
1050 GNUNET_free (src_filename);
1052 /* Calculcate peers */
1053 if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
1055 ph.N_peers_start = DEFAULT_PEERS_START;
1056 ph.N_peers_end = DEFAULT_PEERS_END;
1058 if (0 == ph.N_address)
1059 ph.N_address = DEFAULT_ADDRESSES;
1061 if (ph.N_peers_start != ph.N_peers_end)
1062 fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n",
1063 ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address, ph.iterations);
1065 fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n",
1066 ph.ats_string, ph.N_peers_end, ph.N_address, ph.iterations);
1068 if (0 == ph.opt_update_percent)
1069 ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE;
1072 solver_cfg = GNUNET_CONFIGURATION_create();
1073 if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load ( solver_cfg, "perf_ats_solver.conf"))))
1079 if (GNUNET_ATS_NetworkTypeCount != load_quotas (solver_cfg,
1080 quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
1087 /* Create array of DLL to store results for iterations */
1088 ph.iterations_results = GNUNET_malloc (sizeof (struct Iteration) * ph.iterations);
1091 ph.env.cfg = solver_cfg;
1092 ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
1093 ph.env.stats = ph.stat;
1094 ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1095 ph.env.addresses = ph.addresses;
1096 ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
1097 ph.env.get_preferences = &get_preferences_cb;
1098 ph.env.get_property = &get_property_cb;
1099 ph.env.network_count = GNUNET_ATS_NetworkTypeCount;
1100 ph.env.info_cb = &solver_info_cb;
1101 ph.env.info_cb_cls = NULL;
1103 int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
1104 for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
1106 ph.env.networks[c] = networks[c];
1107 ph.env.out_quota[c] = quotas_out[c];
1108 ph.env.in_quota[c] = quotas_in[c];
1109 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading network quotas: `%s' %llu %llu \n",
1110 GNUNET_ATS_print_network_type(ph.env.networks[c]),
1111 ph.env.out_quota[c],
1112 ph.env.in_quota[c]);
1114 GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
1116 GNUNET_asprintf (&plugin, "libgnunet_plugin_ats_%s", ph.ats_string);
1117 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s'\n"), ph.ats_string);
1118 if (NULL == (ph.solver = GNUNET_PLUGIN_load (plugin, &ph.env)))
1120 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), plugin);
1125 /* Do the benchmark */
1126 for (ph.current_iteration = 1; ph.current_iteration <= ph.iterations; ph.current_iteration++)
1129 evaluate (ph.current_iteration);
1133 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Unloading solver `%s'\n"), ph.ats_string);
1134 GNUNET_PLUGIN_unload (plugin, ph.solver);
1135 GNUNET_free (plugin);
1136 GNUNET_CONFIGURATION_destroy (solver_cfg);
1137 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
1142 main (int argc, char *argv[])
1144 /* extract command line arguments */
1145 ph.opt_update_percent = 0;
1146 ph.N_peers_start = 0;
1149 ph.ats_string = NULL;
1150 ph.create_plot = GNUNET_NO;
1151 ph.measure_updates = GNUNET_NO;
1154 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1155 { 'a', "addresses", NULL,
1156 gettext_noop ("addresses to use"),
1157 1, &GNUNET_GETOPT_set_uint, &ph.N_address },
1158 { 's', "start", NULL,
1159 gettext_noop ("start with peer"),
1160 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_start },
1162 gettext_noop ("end with peer"),
1163 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_end },
1164 { 'i', "iterations", NULL,
1165 gettext_noop ("number of iterations used for averaging (default: 1)"),
1166 1, &GNUNET_GETOPT_set_uint, &ph.iterations },
1167 { 'p', "percentage", NULL,
1168 gettext_noop ("update a fix percentage of addresses"),
1169 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_percent },
1170 { 'g', "gnuplot", NULL,
1171 gettext_noop ("create GNUplot file"),
1172 0, &GNUNET_GETOPT_set_one, &ph.create_plot},
1173 { 'u', "update", NULL,
1174 gettext_noop ("measure updates"),
1175 0, &GNUNET_GETOPT_set_one, &ph.measure_updates},
1176 GNUNET_GETOPT_OPTION_END
1179 GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
1184 /* end of file perf_ats_solver.c */