first quick hack for parallelizing benchmark

This commit is contained in:
Christian Grothoff 2018-08-07 22:10:38 +02:00
parent 8a782ce292
commit 3197125dbe
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
2 changed files with 125 additions and 79 deletions

View File

@ -1,5 +1,5 @@
{
"url": "payto://x-taler-bank/localhost:8082/2",
"salt": "CCTBC3YW3FNZMP853PPD6XV5KFGNKRQJ1JRFRMF9KESTVYET6MN9P7YM8RA848E6K1G3PNNZZGQCSV0J2JKETZ7QE40NY41GE6V1GGG",
"master_sig": "RPDXZXNDPMPY3V4MJH0KHDRWAQ7HK7XBHKP2XQJX8MJKY7PC95002PAJ775630EGGAMY46JJJADHV5DKJ7GPQT0KPRWBV1YEM1M342R"
"salt": "N4KW3895XVGNTF2P135TAAYRY3Q452TP2RMAYVHPQ1ARD17T0KJ9XJH4CKY560S6D549C7VDNPSNA25FY6A9D6QYPTE4V85VE6SRSG8",
"master_sig": "GDVZM7ZNFS4KBWK37KZA1HA66KA374QZDZKANTCXH5G8JS2F4X73ZGXNMHX2FNXP93AZS1SCPVMVAVVBT7F4SQ8AH6SP5SCBZDRFW10"
}

View File

@ -39,7 +39,6 @@
/* Error codes. */
enum BenchmarkError {
MISSING_BANK_URL,
FAILED_TO_LAUNCH_BANK,
BAD_CLI_ARG,
@ -47,6 +46,7 @@ enum BenchmarkError {
NO_CONFIG_FILE_GIVEN
};
/**
* Probability that a spent coin will be refreshed.
*/
@ -62,7 +62,7 @@ enum BenchmarkError {
/**
* Account number of the merchant. Fakebank likes any number,
* the only requirement is that this number then matches the
* number given when building payto URLs at deposit time.
* number given when building payto URLs at deposit time.
*/
#define USER_ACCOUNT_NUMBER 3
@ -104,12 +104,6 @@ struct Account
*/
static struct Account exchange_bank_account;
/**
* Exchange URL; never used, just needed by exchange preparator.
*/
static char *exchange_url;
/**
* Time snapshot taken right before executing the CMDs.
*/
@ -136,6 +130,11 @@ static unsigned int howmany_refreshes;
*/
static unsigned int howmany_coins = 1;
/**
* How many clients we want to create.
*/
static unsigned int howmany_clients = 1;
/**
* Log level used during the run.
*/
@ -162,7 +161,6 @@ static char *currency;
* It is kept as a way to make the macro more auto-descriptive
* where it is called.
*/
#define ALLOCATE_AMOUNTS(...) \
char *AMOUNT_5; \
char *AMOUNT_4; \
@ -197,9 +195,9 @@ pick_exchange_account_cb (void *cls,
const char **s = cls;
*s = section;
}
}
/**
* Parse payto:// account URL (only account information,
* wire subject and amount are ignored).
@ -273,7 +271,7 @@ parse_payto (const char *account_url,
"%llu",
&port))
{
GNUNET_break (0);
GNUNET_break (0);
TALER_LOG_ERROR ("Malformed host from payto:// URI\n");
GNUNET_free (account->hostname);
return TALER_EC_PAYTO_MALFORMED;
@ -293,7 +291,7 @@ parse_payto (const char *account_url,
(GNUNET_SYSERR != GNUNET_asprintf
(&account->bank_base_url,
"https://%s",
account->hostname));
account->hostname));
}
}
return TALER_EC_NONE;
@ -442,7 +440,7 @@ run (void *cls,
unit[5] = TALER_TESTING_cmd_end ();
}
else unit[2] = TALER_TESTING_cmd_end ();
all_commands[1 + i] = TALER_TESTING_cmd_batch ("unit",
unit);
}
@ -455,6 +453,66 @@ run (void *cls,
result = 1;
}
/**
* Run the benchmark in parallel in many (client) processes
* and summarize result.
*
* @param main_cb main function to run per process
* @param main_cb_cls closure for @a main_cb
* @param config_file configuration file to use
* @param exchange_url exchange URL to use
* @return #GNUNET_OK on success
*/
static int
parallel_benchmark (TALER_TESTING_Main main_cb,
void *main_cb_cls,
const char *config_file,
const char *exchange_url)
{
int result;
pid_t cpids[howmany_clients];
int wstatus;
result = GNUNET_OK;
for (unsigned int i=0;i<howmany_clients;i++)
{
if (0 == (cpids[i] = fork ()))
{
/* I am the child, do the work! */
result = TALER_TESTING_setup_with_exchange
(run,
NULL,
cfg_filename);
if (GNUNET_OK == result)
exit (0);
else
exit (1);
}
if (-1 == cpids[i])
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
"fork");
howmany_clients = i;
result = GNUNET_SYSERR;
break;
}
/* fork() success, continue starting more processes! */
}
/* collect all children */
for (unsigned int i=0;i<howmany_clients;i++)
{
waitpid (cpids[i],
&wstatus,
0);
if ( (!WIFEXITED (wstatus)) ||
(0 != WEXITSTATUS (wstatus)) )
result = GNUNET_SYSERR;
}
return result;
}
/**
* The main function of the serve tool
*
@ -466,76 +524,60 @@ int
main (int argc,
char *const *argv)
{
unsetenv ("XDG_DATA_HOME");
unsetenv ("XDG_CONFIG_HOME");
char *exchange_url;
struct GNUNET_OS_Process *compute_wire_response;
struct GNUNET_CONFIGURATION_Handle *cfg;
struct GNUNET_GETOPT_CommandLineOption options[] = {
GNUNET_GETOPT_option_cfgfile
(&cfg_filename),
GNUNET_GETOPT_option_version
(PACKAGE_VERSION " " VCS_VERSION),
GNUNET_GETOPT_option_help
("Exchange benchmark"),
GNUNET_GETOPT_option_loglevel
(&loglev),
GNUNET_GETOPT_option_uint
('n',
"coins-number",
"CN",
"How many coins we should instantiate",
&howmany_coins),
GNUNET_GETOPT_option_string
('l',
"logfile",
"LF",
"will log to file LF",
&logfile),
GNUNET_GETOPT_option_mandatory
(GNUNET_GETOPT_option_cfgfile (&cfg_filename)),
GNUNET_GETOPT_option_version (PACKAGE_VERSION " " VCS_VERSION),
GNUNET_GETOPT_option_help ("Exchange benchmark"),
GNUNET_GETOPT_option_loglevel (&loglev),
GNUNET_GETOPT_option_uint ('n',
"coins-number",
"CN",
"How many coins we should instantiate",
&howmany_coins),
GNUNET_GETOPT_option_uint ('p',
"parallelism",
"NPROCS",
"How many client processes we should run",
&howmany_clients),
GNUNET_GETOPT_option_string ('l',
"logfile",
"LF",
"will log to file LF",
&logfile),
GNUNET_GETOPT_OPTION_END
};
if (GNUNET_SYSERR == (result = GNUNET_GETOPT_run
("taler-exchange-benchmark",
options,
argc,
argv)))
unsetenv ("XDG_DATA_HOME");
unsetenv ("XDG_CONFIG_HOME");
if (GNUNET_SYSERR ==
(result = GNUNET_GETOPT_run ("taler-exchange-benchmark",
options,
argc,
argv)))
{
TALER_LOG_ERROR ("Unparsable CLI options\n");
return BAD_CLI_ARG;
}
GNUNET_log_setup ("taler-exchange-benchmark",
NULL == loglev ? "INFO" : loglev,
logfile);
if (NULL == cfg_filename)
{
TALER_LOG_ERROR ("-c option is mandatory\n");
return NO_CONFIG_FILE_GIVEN;
}
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK != GNUNET_CONFIGURATION_load
(cfg,
cfg_filename))
if (GNUNET_OK !=
GNUNET_CONFIGURATION_load (cfg,
cfg_filename))
{
TALER_LOG_ERROR ("Could not parse configuration\n");
return BAD_CONFIG_FILE;
}
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string
(cfg,
"taler",
"currency",
&currency))
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"taler",
"currency",
&currency))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"taler",
@ -543,13 +585,19 @@ main (int argc,
GNUNET_CONFIGURATION_destroy (cfg);
return BAD_CONFIG_FILE;
}
if (howmany_clients > 1024)
{
TALER_LOG_ERROR ("-p option value given is too large\n");
return BAD_CLI_ARG;
}
{
char *bank_details_section;
char *exchange_payto_url;
GNUNET_CONFIGURATION_iterate_sections
(cfg,
(cfg,
pick_exchange_account_cb,
&bank_details_section);
@ -582,21 +630,19 @@ main (int argc,
" is your PATH correct?\n");
return GNUNET_NO;
}
GNUNET_OS_process_wait
(compute_wire_response);
GNUNET_OS_process_destroy
(compute_wire_response);
GNUNET_OS_process_wait (compute_wire_response);
GNUNET_OS_process_destroy (compute_wire_response);
GNUNET_assert
/* Takes care of dropping all tables. */
(GNUNET_OK == TALER_TESTING_prepare_exchange
(cfg_filename,
&exchange_url)); // never used, we do all via handle.
result = TALER_TESTING_setup_with_exchange
(run,
NULL,
cfg_filename);
&exchange_url));
result = parallel_benchmark (&run,
NULL,
cfg_filename,
exchange_url);
GNUNET_free (exchange_url);
duration = GNUNET_TIME_absolute_get_duration (start_time);
TALER_LOG_INFO ("Executed W=%u, D=%u, R=%u, operations in %s\n",
@ -605,7 +651,7 @@ main (int argc,
howmany_refreshes,
GNUNET_STRINGS_relative_time_to_string
(duration,
GNUNET_YES));
GNUNET_NO));
return (GNUNET_OK == result) ? 0 : result;
}