perf_ats_mlp.c | perf_ats_mlp.c | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
WITHOUT ANY WARRANTY; without even the implied warranty of | WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
General Public License for more details. | General Public License for more details. | |||
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | |||
along with GNUnet; see the file COPYING. If not, write to the | along with GNUnet; see the file COPYING. If not, write to the | |||
Free Software Foundation, Inc., 59 Temple Place - Suite 330, | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |||
Boston, MA 02111-1307, USA. | Boston, MA 02111-1307, USA. | |||
*/ | */ | |||
/** | /** | |||
* @file ats/test_ats_mlp.c | * @file ats/perf_ats_mlp | |||
* @brief test for the MLP solver | * @brief performance test for the MLP solver | |||
* @author Christian Grothoff | * @author Christian Grothoff | |||
* @author Matthias Wachs | * @author Matthias Wachs | |||
*/ | */ | |||
#include "platform.h" | #include "platform.h" | |||
#include "gnunet_util_lib.h" | #include "gnunet_util_lib.h" | |||
#include "gnunet_statistics_service.h" | #include "gnunet_statistics_service.h" | |||
#include "gnunet-service-ats_addresses_mlp.h" | #include "gnunet-service-ats_addresses_mlp.h" | |||
#define VERBOSE GNUNET_YES | ||||
#define VERBOSE_ARM GNUNET_NO | ||||
#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_U NIT_SECONDS, 3) | #define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_U NIT_SECONDS, 3) | |||
#define MLP_MAX_ITERATIONS INT_MAX | #define MLP_MAX_ITERATIONS INT_MAX | |||
#define DEF_PEERS 10 | ||||
#define DEF_ADDRESSES_PER_PEER 5 | ||||
#define DEF_ATS_VALUES 2 | ||||
#define DEF_ATS_MAX_DELAY 30 | ||||
#define DEF_ATS_MAX_DISTANCE 3 | ||||
static unsigned int peers; | ||||
static unsigned int addresses; | ||||
static unsigned int numeric; | ||||
static unsigned int update_percentage; | ||||
static int start; | ||||
static int end; | ||||
struct ATS_Peer *p; | ||||
struct ATS_Address *a; | ||||
static int ret; | static int ret; | |||
struct GNUNET_STATISTICS_Handle * stats; | static struct GNUNET_CONTAINER_MultiHashMap * amap; | |||
static struct GAS_MLP_Handle *mlp; | ||||
GNUNET_SCHEDULER_TaskIdentifier shutdown_task; | ||||
struct PeerContext | ||||
{ | ||||
struct GNUNET_PeerIdentity id; | ||||
struct Address *addr; | ||||
}; | ||||
struct Address | ||||
{ | ||||
char *plugin; | ||||
size_t plugin_len; | ||||
void *addr; | ||||
size_t addr_len; | ||||
struct GNUNET_ATS_Information *ats; | ||||
int ats_count; | ||||
void *session; | ||||
}; | ||||
void | ||||
do_shutdown (void *cls, | ||||
const struct GNUNET_SCHEDULER_TaskContext *tc) | ||||
{ | ||||
unsigned int ca; | ||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); | ||||
if (NULL != mlp) | ||||
{ | ||||
GAS_mlp_done (mlp); | ||||
mlp = NULL; | ||||
} | ||||
if (NULL != a) | ||||
{ | ||||
for (ca=0; ca < (peers * addresses); ca++) | ||||
{ | ||||
GNUNET_free (a[ca].plugin); | ||||
GNUNET_free (a[ca].ats); | ||||
} | ||||
} | ||||
if (NULL != amap) | ||||
GNUNET_CONTAINER_multihashmap_destroy(amap); | ||||
GNUNET_free_non_null (a); | ||||
GNUNET_free_non_null (p); | ||||
} | ||||
static void | ||||
update_addresses (struct ATS_Address * a, unsigned int addrs, unsigned int | ||||
percentage) | ||||
{ | ||||
if (percentage == 0) | ||||
return; | ||||
unsigned int ua = (addrs) * ((float) percentage / 100); | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating %u of %u addresses per peer | ||||
\n", ua, addrs); | ||||
struct GNUNET_CONTAINER_MultiHashMap * addresses; | unsigned int updated[addrs]; | |||
unsigned int u_types[DEF_ATS_VALUES]; | ||||
unsigned int updates = 0; | ||||
unsigned int u_type = 0; | ||||
unsigned int u_val = 0; | ||||
unsigned int cur = 0; | ||||
u_types[0] = 0; | ||||
u_types[1] = 0; | ||||
for (cur = 0; cur < addrs; cur ++) | ||||
{ | ||||
updated[cur] = 0; | ||||
} | ||||
cur = 0; | ||||
while (updates < ua) | ||||
{ | ||||
cur = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, addrs); | ||||
if (0 == updated[cur]) | ||||
{ | ||||
u_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_AT | ||||
S_VALUES); | ||||
switch (u_type) { | ||||
case 0: | ||||
do | ||||
{ | ||||
u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, D | ||||
EF_ATS_MAX_DELAY); | ||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DELAY from %u to | ||||
%u\n",a[cur].ats[u_type].value, u_val); | ||||
} | ||||
while (a[cur].ats[u_type].value == u_val); | ||||
break; | ||||
case 1: | ||||
do | ||||
{ | ||||
u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, D | ||||
EF_ATS_MAX_DISTANCE); | ||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DISTANCE from %u | ||||
to %u\n",a[cur].ats[u_type].value, u_val); | ||||
} | ||||
while (a[cur].ats[u_type].value == u_val); | ||||
break; | ||||
default: | ||||
GNUNET_break (0); | ||||
break; | ||||
} | ||||
u_types[u_type]++; | ||||
a[cur].ats[u_type].value = u_val; | ||||
updated[cur] = 1; | ||||
GAS_mlp_address_update(mlp, amap, &a[cur]); | ||||
updates++; | ||||
} | ||||
} | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated %u delay and %u distance val | ||||
ues\n", u_types[0], u_types[1]); | ||||
struct GAS_MLP_Handle *mlp; | } | |||
static void | static void | |||
check (void *cls, char *const *args, const char *cfgfile, | check (void *cls, char *const *args, const char *cfgfile, | |||
const struct GNUNET_CONFIGURATION_Handle *cfg) | const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
{ | { | |||
unsigned int c = 0; | ||||
unsigned int c2 = 0; | ||||
unsigned int ca = 0; | ||||
int update = GNUNET_NO; | ||||
int range = GNUNET_NO; | ||||
int res; | ||||
#if !HAVE_LIBGLPK | #if !HAVE_LIBGLPK | |||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); | |||
ret = 1; | ret = 1; | |||
return; | return; | |||
#endif | #endif | |||
struct ATS_Address addr[10]; | ||||
stats = GNUNET_STATISTICS_create("ats", cfg); | ||||
addresses = GNUNET_CONTAINER_multihashmap_create (10); | ||||
GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_WEAK, &addr[0].pee | ||||
r.hashPubKey); | ||||
addr[0].mlp_information = NULL; | ||||
addr[0].next = NULL; | ||||
addr[0].prev = NULL; | ||||
addr[0].plugin = strdup ("dummy"); | ||||
addr[1].peer = addr[0].peer; | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up %u peers with %u address | |||
addr[1].mlp_information = NULL; | es per peer\n", peers, addresses); | |||
addr[1].next = NULL; | ||||
addr[1].prev = NULL; | ||||
addr[1].plugin = strdup ("dummy2"); | ||||
GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &a | ||||
ddr[0], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||||
mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS) ; | mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS) ; | |||
if (NULL == mlp) | ||||
{ | ||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to init MLP\n"); | ||||
ret = 1; | ||||
if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||||
GNUNET_SCHEDULER_cancel(shutdown_task); | ||||
shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||||
} | ||||
if (peers == 0) | ||||
peers = DEF_PEERS; | ||||
if (addresses == 0) | ||||
addresses = DEF_ADDRESSES_PER_PEER; | ||||
p = GNUNET_malloc (peers * sizeof (struct ATS_Peer)); | ||||
a = GNUNET_malloc (peers * addresses * sizeof (struct ATS_Address)); | ||||
amap = GNUNET_CONTAINER_multihashmap_create(addresses * peers); | ||||
mlp->auto_solve = GNUNET_NO; | ||||
if (start == 0) | ||||
start = 0; | ||||
if (end == 0) | ||||
end = -1; | ||||
if ((start != -1) && (end != -1)) | ||||
{ | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem starting from %u t | ||||
o %u\n", start , end); | ||||
range = GNUNET_YES; | ||||
} | ||||
else | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem for %u peers\n", p | ||||
eers); | ||||
if ((update_percentage >= 0) && (update_percentage <= 100)) | ||||
{ | ||||
update = GNUNET_YES; | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Benchmarking with existing presolu | ||||
tion and %u%% updated addresses\n", update_percentage); | ||||
} | ||||
else if ((update_percentage > 100) && (update_percentage != UINT_MAX)) | ||||
{ | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Invalid percentage: %u\n", update_ | ||||
percentage); | ||||
ret = 1; | ||||
return; | ||||
} | ||||
for (c=0; c < peers; c++) | ||||
{ | ||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up peer %u\n", c); | ||||
GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_NONCE, &p[c].id. | ||||
hashPubKey); | ||||
for (c2=0; c2 < addresses; c2++) | ||||
{ | ||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u for peer | ||||
%u\n", c2, c); | ||||
/* Setting required information */ | ||||
a[ca].mlp_information = NULL; | ||||
a[ca].prev = NULL; | ||||
a[ca].next = NULL; | ||||
/* Setting address */ | ||||
a[ca].peer = p[c].id; | ||||
a[ca].plugin = GNUNET_strdup("test"); | ||||
a[ca].atsp_network_type = GNUNET_ATS_NET_LOOPBACK; | ||||
a[ca].ats = GNUNET_malloc (DEF_ATS_VALUES * sizeof (struct GNUNET_ATS | ||||
_Information)); | ||||
a[ca].ats[0].type = GNUNET_ATS_QUALITY_NET_DELAY; | ||||
a[ca].ats[0].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_W | ||||
EAK, DEF_ATS_MAX_DELAY); | ||||
a[ca].ats[1].type = GNUNET_ATS_QUALITY_NET_DISTANCE; | ||||
a[ca].ats[1].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_W | ||||
EAK, DEF_ATS_MAX_DISTANCE); | ||||
a[ca].ats_count = 2; | ||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u\n", ca); | ||||
GNUNET_CONTAINER_multihashmap_put (amap, &a[ca].peer.hashPubKey, &a[c | ||||
a], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||||
GAS_mlp_address_update(mlp, amap, &a[ca]); | ||||
ca++; | ||||
} | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem contains %u peers and %u a | ||||
dresses\n", mlp->c_p, mlp->addr_in_problem); | ||||
if (((GNUNET_YES == range) && (((start >= 0) && ((c+1) >= start)) && (c | ||||
<= end))) || ((c+1) == peers)) | ||||
{ | ||||
GNUNET_assert ((c+1) == mlp->c_p); | ||||
GNUNET_assert ((c+1) * addresses == mlp->addr_in_problem); | ||||
/* Solving the problem */ | ||||
struct GAS_MLP_SolutionContext ctx; | ||||
res = GAS_mlp_solve_problem(mlp, &ctx); | ||||
if (GNUNET_NO == update) | ||||
{ | ||||
if (GNUNET_OK == res) | ||||
{ | ||||
GNUNET_assert (GNUNET_OK == ctx.lp_result); | ||||
GNUNET_assert (GNUNET_OK == ctx.mlp_result); | ||||
if (GNUNET_YES == numeric) | ||||
printf ("%u;%u;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem, (un | ||||
signed long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_d | ||||
uration.rel_value); | ||||
else | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem solved for %u peer | ||||
s with %u address successfully (LP: %llu ms / MLP: %llu ms)\n", | ||||
mlp->c_p, mlp->addr_in_problem, ctx.lp_duration.rel_value, | ||||
ctx.mlp_duration.rel_value); | ||||
} | ||||
else | ||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving problem with %u pee | ||||
rs and %u addresses failed\n", c, c2); | ||||
} | ||||
else | ||||
{ | ||||
struct GAS_MLP_SolutionContext uctx; | ||||
/* Update addresses */ | ||||
update_addresses (a, (c+1) * c2, update_percentage); | ||||
/* Solve again */ | ||||
res = GAS_mlp_solve_problem(mlp, &uctx); | ||||
if (GNUNET_OK == res) | ||||
{ | ||||
GNUNET_assert (GNUNET_OK == uctx.lp_result); | ||||
GNUNET_assert (GNUNET_OK == uctx.mlp_result); | ||||
if (GNUNET_YES == numeric) | ||||
printf ("%u;%u;%llu;%llu;%llu;%llu\n",mlp->c_p, mlp->addr_in_pr | ||||
oblem, | ||||
(unsigned long long) ctx.lp_duration.rel_value, (unsigned l | ||||
ong long) ctx.mlp_duration.rel_value, | ||||
(unsigned long long) uctx.lp_duration.rel_value, (unsigned | ||||
long long) uctx.mlp_duration.rel_value); | ||||
else | ||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated problem solved for | ||||
%u peers with %u address successfully (Initial: LP/MLP: %llu/%llu ms, Upda | ||||
te: %llu/%llu ms)\n", | ||||
mlp->c_p, mlp->addr_in_problem, | ||||
(unsigned long long) ctx.lp_duration.rel_value, (unsigned l | ||||
ong long) ctx.mlp_duration.rel_value, | ||||
(unsigned long long) uctx.lp_duration.rel_value, (unsigned | ||||
long long) uctx.mlp_duration.rel_value); | ||||
} | ||||
else | ||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving updated problem wit | ||||
h %u peers and %u addresses failed\n", c, c2); | ||||
} | ||||
} | ||||
} | ||||
if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||||
GNUNET_SCHEDULER_cancel(shutdown_task); | ||||
shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||||
/* Add a new address */ | ||||
#if 0 | ||||
GAS_mlp_address_update (mlp, addresses, &addr[0]); | ||||
GNUNET_assert (mlp != NULL); | ||||
GNUNET_assert (mlp->addr_in_problem == 1); | ||||
/* Update an new address */ | ||||
GAS_mlp_address_update (mlp, addresses, &addr[0]); | ||||
GNUNET_assert (mlp->addr_in_problem == 1); | ||||
/* Add a second address for same peer */ | ||||
GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &a | ||||
ddr[1], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||||
GAS_mlp_address_update (mlp, addresses, &addr[1]); | ||||
GNUNET_assert (mlp->addr_in_problem == 2); | ||||
/* Delete an address */ | ||||
GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[0].peer.hashPubKey | ||||
, &addr[0]); | ||||
GAS_mlp_address_delete (mlp, addresses, &addr[0]); | ||||
GAS_mlp_address_delete (mlp, addresses, &addr[1]); | ||||
#endif | ||||
GAS_mlp_done (mlp); | ||||
GNUNET_free (addr[0].plugin); | ||||
GNUNET_free (addr[1].plugin); | ||||
GNUNET_CONTAINER_multihashmap_destroy (addresses); | ||||
GNUNET_STATISTICS_destroy(stats, GNUNET_NO); | ||||
ret = 0; | ||||
return; | ||||
} | } | |||
int | int | |||
main (int argc, char *argv[]) | main (int argc, char *argv[]) | |||
{ | { | |||
/* Init invalid */ | ||||
static char *const argv2[] = { "test_ats_mlp", | update_percentage = UINT_MAX; | |||
"-c", | ||||
"test_ats_api.conf", | ||||
#if VERBOSE | ||||
"-L", "DEBUG", | ||||
#else | ||||
"-L", "WARNING", | ||||
#endif | ||||
NULL | ||||
}; | ||||
static struct GNUNET_GETOPT_CommandLineOption options[] = { | static struct GNUNET_GETOPT_CommandLineOption options[] = { | |||
{'a', "addresses", NULL, | ||||
gettext_noop ("addresses per peer"), 1, | ||||
&GNUNET_GETOPT_set_uint, &addresses}, | ||||
{'p', "peers", NULL, | ||||
gettext_noop ("peers"), 1, | ||||
&GNUNET_GETOPT_set_uint, &peers}, | ||||
{'n', "numeric", NULL, | ||||
gettext_noop ("numeric output only"), 0, | ||||
&GNUNET_GETOPT_set_one, &numeric}, | ||||
{'e', "end", NULL, | ||||
gettext_noop ("end solving problem"), 1, | ||||
&GNUNET_GETOPT_set_uint, &end}, | ||||
{'s', "start", NULL, | ||||
gettext_noop ("start solving problem"), 1, | ||||
&GNUNET_GETOPT_set_uint, &start}, | ||||
{'u', "update", NULL, | ||||
gettext_noop ("benchmark with existing solution (address updates)"), 1 | ||||
, | ||||
&GNUNET_GETOPT_set_uint, &update_percentage}, | ||||
GNUNET_GETOPT_OPTION_END | GNUNET_GETOPT_OPTION_END | |||
}; | }; | |||
GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, | GNUNET_PROGRAM_run (argc, argv, | |||
"test_ats_mlp", "nohelp", options, | "perf_ats_mlp", "nohelp", options, | |||
&check, NULL); | &check, NULL); | |||
return ret; | return ret; | |||
} | } | |||
/* end of file test_ats_api_bandwidth_consumption.c */ | /* end of file perf_ats_mlp.c */ | |||
End of changes. 16 change blocks. | ||||
75 lines changed or deleted | 336 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |