2 This file is part of GNUnet.
3 Copyright (C) 2010,2011 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU 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.
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.
16 * @file ats/perf_ats_solver.c
17 * @brief generic performance test for ATS solvers
18 * @author Christian Grothoff
19 * @author Matthias Wachs
22 #include "gnunet_util_lib.h"
23 #include "gnunet_statistics_service.h"
24 #include "gnunet-service-ats_addresses.h"
25 #include "gnunet-service-ats_plugins.h"
26 #include "gnunet-service-ats_normalization.h"
27 #include "gnunet-service-ats_preferences.h"
28 #include "gnunet_ats_service.h"
29 #include "gnunet_ats_plugin.h"
30 #include "test_ats_api_common.h"
32 #define DEFAULT_UPDATE_PERCENTAGE 20
33 #define DEFAULT_PEERS_START 10
34 #define DEFAULT_PEERS_END 10
35 #define DEFAULT_ADDRESSES 10
36 #define DEFAULT_ATS_COUNT 2
40 * Handle for statistics.
42 struct GNUNET_STATISTICS_Handle *GSA_stats;
45 * Handle for ATS address component
52 struct PerfPeer *peers;
57 struct GNUNET_ATS_SolverFunctions *sf;
62 struct GNUNET_STATISTICS_Handle *stat;
65 * A multihashmap to store all addresses
67 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
72 struct GNUNET_ATS_PluginEnvironment env;
75 * Array for results for each iteration with length iterations
77 struct Iteration *iterations_results;
82 struct Result *current_result;
85 * Current number of peers benchmarked
90 * Current number of addresses benchmarked
95 * Solver description as string
100 * Configured ATS solver
105 * #peers to start benchmarking with
110 * #peers to end benchmarking with
115 * #addresses to benchmarking with
120 * Percentage of peers to update
122 int opt_update_percent;
125 * Create gnuplot file
135 * Number of iterations
137 int total_iterations;
142 int current_iteration;
145 * Is a bulk operation running?
150 * Is a bulk operation running?
152 int expecting_solution;
155 * Was the problem just updates?
157 int performed_update;
161 * Data structure to store results for a single iteration
165 struct Result **results_array;
167 struct Result **update_results_array;
172 * Result for a solver calculcation
177 * Previous element in the linked list
182 * Next element in the linked list
187 * Number of peers this solution included
192 * Number of addresses per peer this solution included
197 * Is this an update or a full solution
202 * Was the solution valid or did the solver fail
207 * Result of the solver
209 enum GAS_Solver_Additional_Information info;
212 * Duration of setting up the problem in the solver
214 struct GNUNET_TIME_Relative d_setup_full;
217 * Duration of solving the LP problem in the solver
220 struct GNUNET_TIME_Relative d_lp_full;
223 * Duration of solving the MLP problem in the solver
226 struct GNUNET_TIME_Relative d_mlp_full;
229 * Duration of solving whole problem in the solver
231 struct GNUNET_TIME_Relative d_total_full;
234 * Start time of setting up the problem in the solver
236 struct GNUNET_TIME_Absolute s_setup;
239 * Start time of solving the LP problem in the solver
242 struct GNUNET_TIME_Absolute s_lp;
245 * Start time of solving the MLP problem in the solver
248 struct GNUNET_TIME_Absolute s_mlp;
251 * Start time of solving whole problem in the solver
253 struct GNUNET_TIME_Absolute s_total;
256 * End time of setting up the problem in the solver
258 struct GNUNET_TIME_Absolute e_setup;
261 * End time of solving the LP problem in the solver
264 struct GNUNET_TIME_Absolute e_lp;
267 * End time of solving the MLP problem in the solver
270 struct GNUNET_TIME_Absolute e_mlp;
273 * End time of solving whole problem in the solver
275 struct GNUNET_TIME_Absolute e_total;
279 * Peer used for the benchmarking
286 struct GNUNET_PeerIdentity id;
289 * Head of linked list of addresses used with this peer
291 struct ATS_Address *head;
294 * Head of linked list of addresses used with this peer
296 struct ATS_Address *tail;
301 * ATS performance handle
303 static struct PerfHandle ph;
319 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
323 GNUNET_free_non_null (ph.peers);
324 GNUNET_free_non_null (ph.iterations_results);
326 GAS_normalization_stop ();
327 GAS_preference_done ();
333 * Create a peer used for benchmarking
335 * @param cp the number of the peer
338 perf_create_peer (int cp)
341 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
342 &ph.peers[cp].id, sizeof (struct GNUNET_PeerIdentity));
343 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
344 GNUNET_i2s (&ph.peers[cp].id));
349 * Perform an update for an address
351 * @param cur the address to update
354 perf_update_address (struct ATS_Address *cur)
360 r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
364 abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
365 rel_val = (100 + (double) abs_val) / 100;
367 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
368 "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
369 GNUNET_i2s (&cur->peer), cur,
370 "GNUNET_ATS_QUALITY_NET_DELAY",
372 ph.sf->s_address_update_property (ph.sf->cls, cur,
373 GNUNET_ATS_QUALITY_NET_DELAY,
377 abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
378 rel_val = (100 + (double) abs_val) / 100;
380 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
381 "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
382 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE",
384 ph.sf->s_address_update_property (ph.sf->cls, cur,
385 GNUNET_ATS_QUALITY_NET_DISTANCE,
395 bandwidth_changed_cb (void *cls,
396 struct ATS_Address *address)
398 if ( (0 == address->assigned_bw_out) && (0 == address->assigned_bw_in) )
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
403 GNUNET_i2s (&address->peer),
405 address->assigned_bw_out,
406 address->assigned_bw_in);
407 if (GNUNET_YES == ph.bulk_running)
413 static const double *
414 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
416 return GAS_preference_get_by_peer (NULL, id);
421 perf_address_initial_update (void *dead,
422 struct GNUNET_CONTAINER_MultiPeerMap * addresses,
423 struct ATS_Address *address)
427 uint32_t random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
428 delay = (100 + (double) random) / 100;
429 ph.sf->s_address_update_property (ph.sf->cls,
430 address, GNUNET_ATS_QUALITY_NET_DELAY,
433 random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
434 distance = (100 + (double) random) / 100;
436 ph.sf->s_address_update_property (ph.sf->cls, address,
437 GNUNET_ATS_QUALITY_NET_DISTANCE,
440 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
441 "Initial update address %p : %.2f %.2f\n",
442 address, delay, distance);
454 do_update_address (void *cls,
455 const struct GNUNET_PeerIdentity *pid,
458 struct DUA_Ctx *ctx = cls;
459 struct ATS_Address *addr = value;
461 if (ctx->c_cur_a == ctx->r)
462 perf_update_address (addr);
469 * Update a certain percentage of peers
471 * @param cp the current number of peers
472 * @param ca the current number of addresses
473 * @param percentage_peers the percentage of peers to update
476 perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int percentage_peers)
484 struct DUA_Ctx dua_ctx;
486 count = cp * ((double) percentage_peers / 100);
487 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
488 "Updating %u of %u peers \n", count, cp);
490 for (c_peer = 0; c_peer < cp; c_peer++)
495 while (c_select < count)
497 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp);
501 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
502 "Updating peer [%u] \n", r);
506 for (c_cur_p = 0; c_cur_p < cp; c_cur_p++)
510 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
511 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
512 "Updating peer [%u] address [%u]\n", c_cur_p, r);
516 GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
517 &ph.peers[c_cur_p].id,
525 * Create an address for a peer
527 * @param cp index of the peer
528 * @param ca index of the address
529 * @return the address
531 static struct ATS_Address *
532 perf_create_address (int cp, int ca)
534 struct ATS_Address *a;
536 a = create_address (&ph.peers[cp].id,
537 "Test 1", "test 1", strlen ("test 1") + 1, 0);
538 GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
539 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
545 * Information callback for the solver
547 * @param op the solver operation
548 * @param stat status of the solver operation
549 * @param add additional solver information
552 solver_info_cb (void *cls,
553 enum GAS_Solver_Operation op,
554 enum GAS_Solver_Status stat,
555 enum GAS_Solver_Additional_Information add)
560 add_info = "GAS_INFO_NONE";
563 add_info = "GAS_INFO_MLP_FULL";
565 case GAS_INFO_UPDATED:
566 add_info = "GAS_INFO_MLP_UPDATED";
568 case GAS_INFO_PROP_ALL:
569 add_info = "GAS_INFO_PROP_ALL";
571 case GAS_INFO_PROP_SINGLE:
572 add_info = "GAS_INFO_PROP_SINGLE";
575 add_info = "INVALID";
582 case GAS_OP_SOLVE_START:
583 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
584 "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
585 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
586 if (GNUNET_NO == ph.expecting_solution)
588 /* We do not expect a solution at the moment */
593 if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result))
595 tmp = GNUNET_new (struct Result);
596 /* Create new result */
597 if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
599 ph.current_result = tmp;
600 //fprintf (stderr,"UPDATE %u %u\n",ph.current_iteration-1, ph.current_p);
601 ph.iterations_results[ph.current_iteration-1].update_results_array[ph.current_p] = tmp;
605 ph.current_result = tmp;
606 //fprintf (stderr,"FULL %u %u\n",ph.current_iteration-1, ph.current_p);
607 ph.iterations_results[ph.current_iteration-1].results_array[ph.current_p] = tmp;
610 ph.current_result->addresses = ph.current_a;
611 ph.current_result->peers = ph.current_p;
612 ph.current_result->s_total = GNUNET_TIME_absolute_get();
613 ph.current_result->d_total_full = GNUNET_TIME_UNIT_FOREVER_REL;
614 ph.current_result->d_setup_full = GNUNET_TIME_UNIT_FOREVER_REL;
615 ph.current_result->d_lp_full = GNUNET_TIME_UNIT_FOREVER_REL;
616 ph.current_result->d_mlp_full = GNUNET_TIME_UNIT_FOREVER_REL;
617 ph.current_result->info = add;
618 if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
620 ph.current_result->update = GNUNET_YES;
624 ph.current_result->update = GNUNET_NO;
629 case GAS_OP_SOLVE_STOP:
630 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
631 "Solver notifies `%s' with result `%s', `%s'\n", "GAS_OP_SOLVE_STOP",
632 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
633 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
635 /* We do not expect a solution at the moment */
640 if (GAS_STAT_SUCCESS == stat)
641 ph.current_result->valid = GNUNET_YES;
643 ph.current_result->valid = GNUNET_NO;
645 if (NULL != ph.current_result)
647 /* Finalize result */
648 ph.current_result->e_total = GNUNET_TIME_absolute_get ();
649 ph.current_result->d_total_full = GNUNET_TIME_absolute_get_difference (
650 ph.current_result->s_total, ph.current_result->e_total);
652 ph.current_result = NULL;
655 case GAS_OP_SOLVE_SETUP_START:
656 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
657 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
658 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
659 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
665 if (GAS_STAT_SUCCESS == stat)
666 ph.current_result->valid = GNUNET_YES;
668 ph.current_result->valid = GNUNET_NO;
670 ph.current_result->s_setup = GNUNET_TIME_absolute_get ();
673 case GAS_OP_SOLVE_SETUP_STOP:
674 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
675 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
676 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
677 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
683 if (GAS_STAT_SUCCESS == stat)
684 ph.current_result->valid = GNUNET_YES;
686 ph.current_result->valid = GNUNET_NO;
688 ph.current_result->e_setup = GNUNET_TIME_absolute_get ();
689 ph.current_result->d_setup_full = GNUNET_TIME_absolute_get_difference (
690 ph.current_result->s_setup, ph.current_result->e_setup);
693 case GAS_OP_SOLVE_MLP_LP_START:
694 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
695 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
696 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
697 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
703 if (GAS_STAT_SUCCESS == stat)
704 ph.current_result->valid = GNUNET_YES;
706 ph.current_result->valid = GNUNET_NO;
708 ph.current_result->s_lp = GNUNET_TIME_absolute_get ();
710 case GAS_OP_SOLVE_MLP_LP_STOP:
711 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
712 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
713 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
714 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
720 if (GAS_STAT_SUCCESS == stat)
721 ph.current_result->valid = GNUNET_YES;
723 ph.current_result->valid = GNUNET_NO;
725 ph.current_result->e_lp = GNUNET_TIME_absolute_get ();
726 ph.current_result->d_lp_full = GNUNET_TIME_absolute_get_difference (
727 ph.current_result->s_lp, ph.current_result->e_lp);
730 case GAS_OP_SOLVE_MLP_MLP_START:
731 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
732 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
733 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
734 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
740 if (GAS_STAT_SUCCESS == stat)
741 ph.current_result->valid = GNUNET_YES;
743 ph.current_result->valid = GNUNET_NO;
745 ph.current_result->s_mlp = GNUNET_TIME_absolute_get ();
747 case GAS_OP_SOLVE_MLP_MLP_STOP:
748 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
749 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
750 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
751 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
757 if (GAS_STAT_SUCCESS == stat)
758 ph.current_result->valid = GNUNET_YES;
760 ph.current_result->valid = GNUNET_NO;
762 ph.current_result->e_mlp = GNUNET_TIME_absolute_get ();
763 ph.current_result->d_mlp_full = GNUNET_TIME_absolute_get_difference (
764 ph.current_result->s_mlp, ph.current_result->e_mlp);
766 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
767 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
768 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
769 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
771 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
772 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
773 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
774 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
775 if (GAS_STAT_SUCCESS != stat)
777 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
778 "Solver `%s' failed to update problem with %u peers and %u address!\n",
779 ph.ats_string, ph.current_p, ph.current_a);
789 * Evaluate results for a specific iteration
791 * @param iteration the iteration to evaluate
794 evaluate (int iteration)
799 for (cp = ph.N_peers_start; cp <= ph.N_peers_end; cp ++)
801 cur = ph.iterations_results[ph.current_iteration-1].results_array[cp];
808 "Missing result for %u peers\n", cp);
813 if (GNUNET_NO == cur->valid)
816 "Total time to solve %s for %u peers %u addresses: %s\n",
817 (GNUNET_YES == cur->update) ? "updated" : "full",
818 cur->peers, cur->addresses, "Failed to solve!");
823 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_total_full.rel_value_us)
826 "Total time to solve %s for %u peers %u addresses: %llu us\n",
827 (GNUNET_YES == cur->update) ? "updated" : "full",
828 cur->peers, cur->addresses,
829 (unsigned long long) cur->d_total_full.rel_value_us);
833 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_setup_full.rel_value_us)
835 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
836 "Total time to setup %s %u peers %u addresses: %llu us\n",
837 (GNUNET_YES == cur->update) ? "updated" : "full",
838 cur->peers, cur->addresses,
839 (unsigned long long) cur->d_setup_full.rel_value_us);
842 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_lp_full.rel_value_us)
844 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
845 "Total time to solve %s LP for %u peers %u addresses: %llu us\n",
846 (GNUNET_YES == cur->update) ? "updated" : "full",
849 (unsigned long long )cur->d_lp_full.rel_value_us);
852 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_mlp_full.rel_value_us)
854 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
855 "Total time to solve %s MLP for %u peers %u addresses: %llu us\n",
856 (GNUNET_YES == cur->update) ? "updated" : "full",
857 cur->peers, cur->addresses,
858 (unsigned long long )cur->d_mlp_full.rel_value_us);
865 get_connectivity_cb (void *cls,
866 const struct GNUNET_PeerIdentity *peer)
868 return GNUNET_CONTAINER_multipeermap_contains (ph.addresses,
874 * Evaluate average results for all iterations
877 write_all_iterations (void)
882 struct GNUNET_DISK_FileHandle *f_full;
883 struct GNUNET_DISK_FileHandle *f_update;
885 char * data_fn_update;
893 if (GNUNET_NO == ph.create_datafile)
896 GNUNET_asprintf (&data_fn_full,
897 "perf_%s_full_%u-%u_%u_%u.data",
903 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
904 "Using data file `%s'\n",
907 f_full = GNUNET_DISK_file_open (data_fn_full,
908 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
909 GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
912 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
913 "Cannot open data file `%s'\n",
915 GNUNET_free (data_fn_full);
919 data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
920 if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_full, data, strlen(data)))
921 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
922 "Cannot write data to log file `%s'\n",
925 data_fn_update = NULL;
926 if (GNUNET_YES == ph.measure_updates)
928 GNUNET_asprintf (&data_fn_update, "perf_%s_update_%u-%u_%u_%u.data",
934 f_update = GNUNET_DISK_file_open (data_fn_update,
935 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
936 GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
937 if (NULL == f_update)
939 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
940 "Cannot open gnuplot file `%s'\n", data_fn_update);
941 GNUNET_free (data_fn_update);
943 GNUNET_DISK_file_close (f_full);
944 GNUNET_free (data_fn_full);
948 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
949 "Using update data file `%s'\n",
952 data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
953 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data)))
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 "Cannot write data to log file `%s'\n",
959 for (c_peer = ph.N_peers_start; c_peer <= ph.N_peers_end; c_peer ++)
965 GNUNET_asprintf(&data_str, "%u;%u",c_peer, ph.N_address);
966 if (ph.measure_updates)
967 GNUNET_asprintf(&data_upd_str, "%u;%u",c_peer, ph.N_address);
968 for (c_iteration = 0; c_iteration < ph.total_iterations; c_iteration ++)
970 struct Result *cur_full_res;
971 struct Result *cur_upd_res;
975 //fprintf (stderr, "P: %u I: %u == %p \n", c_peer, c_iteration, cur_res);
976 cur_full_res = ph.iterations_results[c_iteration].results_array[c_peer];
979 if (NULL == cur_full_res)
982 if (ph.measure_updates)
984 cur_upd_res = ph.iterations_results[c_iteration].update_results_array[c_peer];
985 data_upd_tmp = GNUNET_strdup (data_upd_str);
986 GNUNET_free (data_upd_str);
987 if (GNUNET_YES == cur_full_res->valid)
989 GNUNET_asprintf (&data_upd_str, "%s;%llu", data_upd_tmp,
990 (NULL == cur_upd_res) ? 0 : cur_upd_res->d_total_full.rel_value_us);
994 GNUNET_asprintf (&data_upd_str, "%s;", data_upd_tmp);
996 GNUNET_free (data_upd_tmp);
1000 //fprintf (stderr, "P: %u I: %u: P %i A %i\n", c_peer, c_iteration, cur_res->peers, cur_res->addresses);
1001 //fprintf (stderr, "D total: %llu\n", (long long unsigned int) cur_res->d_total.rel_value_us);
1003 data_tmp = GNUNET_strdup (data_str);
1004 GNUNET_free (data_str);
1005 if (GNUNET_YES == cur_full_res->valid)
1007 GNUNET_asprintf (&data_str, "%s;%llu", data_tmp,
1008 cur_full_res->d_total_full.rel_value_us);
1012 GNUNET_asprintf (&data_str, "%s;", data_tmp);
1015 GNUNET_free (data_tmp);
1017 data_tmp = GNUNET_strdup (data_str);
1018 GNUNET_free (data_str);
1019 GNUNET_asprintf (&data_str, "%s\n", data_tmp);
1020 GNUNET_free (data_tmp);
1022 fprintf (stderr, "Result full solution: %s\n", data_str);
1023 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data_str, strlen(data_str)))
1025 GNUNET_free (data_str);
1027 if (ph.measure_updates)
1029 data_upd_tmp = GNUNET_strdup (data_upd_str);
1030 GNUNET_free (data_upd_str);
1031 GNUNET_asprintf (&data_upd_str, "%s\n", data_upd_tmp);
1032 GNUNET_free (data_upd_tmp);
1034 fprintf (stderr, "Result updated solution: `%s'\n", data_upd_str);
1035 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data_upd_str, strlen(data_upd_str)))
1037 GNUNET_free (data_upd_str);
1041 if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full)))
1042 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
1044 GNUNET_free_non_null (data_fn_full);
1046 if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_update)))
1047 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
1049 GNUNET_free_non_null (data_fn_update);
1054 do_delete_address (void *cls,
1055 const struct GNUNET_PeerIdentity *pid,
1058 struct ATS_Address *cur = value;
1060 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1061 "Deleting addresses for peer %u\n",
1063 GNUNET_assert (GNUNET_OK ==
1064 GNUNET_CONTAINER_multipeermap_remove (ph.addresses,
1067 ph.sf->s_del (ph.sf->cls, cur);
1068 GNUNET_free_non_null (cur->atsi);
1075 * Run a performance iteration
1078 perf_run_iteration (void)
1082 int count_p = ph.N_peers_end;
1083 int count_a = ph.N_address;
1084 struct ATS_Address * cur_addr;
1087 ph.iterations_results[ph.current_iteration-1].results_array = GNUNET_malloc ((count_p + 1) * sizeof (struct Result *));
1088 if (ph.measure_updates)
1089 ph.iterations_results[ph.current_iteration-1].update_results_array = GNUNET_malloc ((count_p + 1) * sizeof (struct Result *));
1090 ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer));
1091 for (cp = 0; cp < count_p; cp++)
1092 perf_create_peer (cp);
1093 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1094 "Iteration %u of %u, added %u peers\n", ph.current_iteration, ph.total_iterations, cp);
1096 for (cp = 0; cp < count_p; cp++)
1098 fprintf (stderr,"%u..", cp);
1099 if (GNUNET_NO == ph.bulk_running)
1101 ph.bulk_running = GNUNET_YES;
1102 ph.sf->s_bulk_start (ph.sf->cls);
1104 ph.current_p = cp + 1;
1105 for (ca = 0; ca < count_a; ca++)
1107 cur_addr = perf_create_address (cp, ca);
1110 /* Random network selection */
1111 //net = 1 + GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_ATS_NetworkTypeCount - 1);
1112 /* Random equally distributed network selection */
1113 net = 1 + (ca % (GNUNET_ATS_NetworkTypeCount - 1));
1114 /* fprintf (stderr, "Network: %u `%s'\n",
1115 * mod_net , GNUNET_ATS_print_network_type(mod_net)); */
1117 cur_addr->atsi = GNUNET_new (struct GNUNET_ATS_Information);
1118 cur_addr->atsi_count = 1;
1119 cur_addr->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
1120 cur_addr->atsi[0].value = htonl (net);
1121 ph.sf->s_add (ph.sf->cls, cur_addr, net);
1123 ph.current_a = ca + 1;
1124 perf_address_initial_update (NULL, ph.addresses, cur_addr);
1125 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1126 "Adding address for peer %u address %u in network %s\n", cp, ca,
1127 GNUNET_ATS_print_network_type(net));
1129 /* Notify solver about request */
1130 ph.sf->s_get (ph.sf->cls, &ph.peers[cp].id);
1132 if (cp + 1 >= ph.N_peers_start)
1134 /* Disable bulk to solve the problem */
1135 if (GNUNET_YES == ph.bulk_running)
1137 ph.expecting_solution = GNUNET_YES;
1138 ph.bulk_running = GNUNET_NO;
1139 ph.sf->s_bulk_stop (ph.sf->cls);
1144 /* Problem is solved by the solver here due to unlocking */
1145 ph.expecting_solution = GNUNET_NO;
1147 /* Update the problem */
1148 if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates))
1151 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1152 "Updating problem with %u peers and %u addresses\n", cp + 1, ca);
1154 ph.expecting_solution = GNUNET_YES;
1155 ph.performed_update = GNUNET_YES;
1156 if (GNUNET_NO == ph.bulk_running)
1158 ph.bulk_running = GNUNET_YES;
1159 ph.sf->s_bulk_start (ph.sf->cls);
1161 perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent);
1162 ph.bulk_running = GNUNET_NO;
1163 ph.sf->s_bulk_stop (ph.sf->cls);
1164 /* Problem is solved by the solver here due to unlocking */
1165 ph.performed_update = GNUNET_NO;
1166 ph.expecting_solution = GNUNET_NO;
1168 GNUNET_assert (GNUNET_NO == ph.bulk_running);
1171 fprintf (stderr,"\n");
1172 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1173 "Done, cleaning up addresses\n");
1174 if (GNUNET_NO == ph.bulk_running)
1176 ph.sf->s_bulk_start (ph.sf->cls);
1177 ph.bulk_running = GNUNET_YES;
1180 for (cp = 0; cp < count_p; cp++)
1182 GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
1187 if (GNUNET_NO == ph.bulk_running)
1189 ph.sf->s_bulk_stop (ph.sf->cls);
1190 ph.bulk_running = GNUNET_NO;
1193 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1194 "Iteration done\n");
1195 GNUNET_free(ph.peers);
1200 run (void *cls, char * const *args, const char *cfgfile,
1201 const struct GNUNET_CONFIGURATION_Handle *cfg)
1203 GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
1205 char *src_filename = GNUNET_strdup (__FILE__);
1206 char *test_filename = cls;
1209 struct GNUNET_CONFIGURATION_Handle *solver_cfg;
1210 unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
1211 unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
1215 /* Extract test name */
1216 if (NULL == (sep = (strstr (src_filename,".c"))))
1218 GNUNET_free (src_filename);
1225 if (NULL != (sep = strstr (test_filename, ".exe")))
1228 if (NULL == (solver = strstr (test_filename, src_filename)))
1230 GNUNET_free (src_filename);
1235 solver += strlen (src_filename) +1;
1237 if (0 == strcmp(solver, "proportional"))
1239 ph.ats_string = "proportional";
1241 else if (0 == strcmp(solver, "mlp"))
1243 ph.ats_string = "mlp";
1245 else if ((0 == strcmp(solver, "ril")))
1247 ph.ats_string = "ril";
1251 GNUNET_free (src_filename);
1256 GNUNET_free (src_filename);
1258 /* Calculcate peers */
1259 if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
1261 ph.N_peers_start = DEFAULT_PEERS_START;
1262 ph.N_peers_end = DEFAULT_PEERS_END;
1264 if (0 == ph.N_address)
1265 ph.N_address = DEFAULT_ADDRESSES;
1268 if (ph.N_peers_start != ph.N_peers_end)
1269 fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n",
1270 ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address, ph.total_iterations);
1272 fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n",
1273 ph.ats_string, ph.N_peers_end, ph.N_address, ph.total_iterations);
1275 if (0 == ph.opt_update_percent)
1276 ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE;
1279 solver_cfg = GNUNET_CONFIGURATION_create();
1280 if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load ( solver_cfg, "perf_ats_solver.conf"))))
1286 if (GNUNET_ATS_NetworkTypeCount != load_quotas (solver_cfg,
1287 quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
1294 /* Create array of DLL to store results for iterations */
1295 ph.iterations_results = GNUNET_malloc (sizeof (struct Iteration) * ph.total_iterations);
1298 ph.env.cfg = solver_cfg;
1299 ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
1300 ph.env.stats = ph.stat;
1301 ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1302 ph.env.addresses = ph.addresses;
1303 ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
1304 ph.env.get_connectivity = &get_connectivity_cb;
1305 ph.env.get_preferences = &get_preferences_cb;
1306 ph.env.network_count = GNUNET_ATS_NetworkTypeCount;
1307 ph.env.info_cb = &solver_info_cb;
1309 for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
1311 ph.env.out_quota[c] = quotas_out[c];
1312 ph.env.in_quota[c] = quotas_in[c];
1313 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1314 "Loading network quotas: `%s' %llu %llu \n",
1315 GNUNET_ATS_print_network_type (c),
1316 ph.env.out_quota[c],
1317 ph.env.in_quota[c]);
1319 GAS_normalization_start ();
1320 GAS_preference_init ();
1322 GNUNET_asprintf (&plugin,
1323 "libgnunet_plugin_ats_%s",
1325 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1326 _("Initializing solver `%s'\n"),
1328 if (NULL == (ph.sf = GNUNET_PLUGIN_load (plugin, &ph.env)))
1330 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1331 _("Failed to initialize solver `%s'!\n"),
1337 /* Do the benchmark */
1338 for (ph.current_iteration = 1; ph.current_iteration <= ph.total_iterations; ph.current_iteration++)
1341 "Iteration %u of %u starting\n",
1342 ph.current_iteration,
1343 ph.total_iterations);
1344 perf_run_iteration ();
1345 evaluate (ph.current_iteration);
1347 "Iteration %u of %u done\n",
1348 ph.current_iteration,
1349 ph.total_iterations);
1351 if (ph.create_datafile)
1352 write_all_iterations ();
1355 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1356 _("Unloading solver `%s'\n"),
1358 GNUNET_PLUGIN_unload (plugin, ph.sf);
1360 GNUNET_free (plugin);
1361 for (c = 0; c < ph.total_iterations; c++ )
1363 for (c2 = ph.N_peers_start; c2 < ph.N_peers_end; c2++ )
1367 if (ph.measure_updates)
1368 GNUNET_free_non_null (ph.iterations_results[c].update_results_array[c2]);
1369 GNUNET_free (ph.iterations_results[c].results_array[c2]);
1371 if (ph.measure_updates)
1372 GNUNET_free (ph.iterations_results[c].update_results_array);
1373 GNUNET_free(ph.iterations_results[c].results_array);
1375 GNUNET_free (ph.iterations_results);
1377 GNUNET_CONFIGURATION_destroy (solver_cfg);
1378 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
1383 * Main function of the benchmark
1385 * @param argc argument count
1386 * @param argv argument values
1389 main (int argc, char *argv[])
1391 /* extract command line arguments */
1392 ph.opt_update_percent = 0;
1393 ph.N_peers_start = 0;
1396 ph.ats_string = NULL;
1397 ph.create_datafile = GNUNET_NO;
1398 ph.measure_updates = GNUNET_NO;
1399 ph.total_iterations = 1;
1401 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1403 GNUNET_GETOPT_option_uint ('a',
1405 gettext_noop ("addresses to use"),
1408 GNUNET_GETOPT_option_uint ('s',
1410 gettext_noop ("start with peer"),
1413 GNUNET_GETOPT_option_uint ('e',
1415 gettext_noop ("end with peer"),
1418 GNUNET_GETOPT_option_uint ('i',
1420 gettext_noop ("number of iterations used for averaging (default: 1)"),
1421 &ph.total_iterations),
1423 GNUNET_GETOPT_option_uint ('p',
1425 gettext_noop ("update a fix percentage of addresses"),
1426 &ph.opt_update_percent),
1428 GNUNET_GETOPT_option_flag ('d',
1430 gettext_noop ("create data file"),
1431 &ph.create_datafile),
1433 GNUNET_GETOPT_option_flag ('u',
1435 gettext_noop ("measure updates"),
1436 &ph.measure_updates),
1438 GNUNET_GETOPT_OPTION_END
1441 GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
1445 /* end of file perf_ats_solver.c */