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", "url": "payto://x-taler-bank/localhost:8082/2",
"salt": "CCTBC3YW3FNZMP853PPD6XV5KFGNKRQJ1JRFRMF9KESTVYET6MN9P7YM8RA848E6K1G3PNNZZGQCSV0J2JKETZ7QE40NY41GE6V1GGG", "salt": "N4KW3895XVGNTF2P135TAAYRY3Q452TP2RMAYVHPQ1ARD17T0KJ9XJH4CKY560S6D549C7VDNPSNA25FY6A9D6QYPTE4V85VE6SRSG8",
"master_sig": "RPDXZXNDPMPY3V4MJH0KHDRWAQ7HK7XBHKP2XQJX8MJKY7PC95002PAJ775630EGGAMY46JJJADHV5DKJ7GPQT0KPRWBV1YEM1M342R" "master_sig": "GDVZM7ZNFS4KBWK37KZA1HA66KA374QZDZKANTCXH5G8JS2F4X73ZGXNMHX2FNXP93AZS1SCPVMVAVVBT7F4SQ8AH6SP5SCBZDRFW10"
} }

View File

@ -39,7 +39,6 @@
/* Error codes. */ /* Error codes. */
enum BenchmarkError { enum BenchmarkError {
MISSING_BANK_URL, MISSING_BANK_URL,
FAILED_TO_LAUNCH_BANK, FAILED_TO_LAUNCH_BANK,
BAD_CLI_ARG, BAD_CLI_ARG,
@ -47,6 +46,7 @@ enum BenchmarkError {
NO_CONFIG_FILE_GIVEN NO_CONFIG_FILE_GIVEN
}; };
/** /**
* Probability that a spent coin will be refreshed. * Probability that a spent coin will be refreshed.
*/ */
@ -104,12 +104,6 @@ struct Account
*/ */
static struct Account exchange_bank_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. * Time snapshot taken right before executing the CMDs.
*/ */
@ -136,6 +130,11 @@ static unsigned int howmany_refreshes;
*/ */
static unsigned int howmany_coins = 1; 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. * 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 * It is kept as a way to make the macro more auto-descriptive
* where it is called. * where it is called.
*/ */
#define ALLOCATE_AMOUNTS(...) \ #define ALLOCATE_AMOUNTS(...) \
char *AMOUNT_5; \ char *AMOUNT_5; \
char *AMOUNT_4; \ char *AMOUNT_4; \
@ -197,9 +195,9 @@ pick_exchange_account_cb (void *cls,
const char **s = cls; const char **s = cls;
*s = section; *s = section;
} }
} }
/** /**
* Parse payto:// account URL (only account information, * Parse payto:// account URL (only account information,
* wire subject and amount are ignored). * wire subject and amount are ignored).
@ -455,6 +453,66 @@ run (void *cls,
result = 1; 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 * The main function of the serve tool
* *
@ -466,45 +524,37 @@ int
main (int argc, main (int argc,
char *const *argv) char *const *argv)
{ {
char *exchange_url;
unsetenv ("XDG_DATA_HOME");
unsetenv ("XDG_CONFIG_HOME");
struct GNUNET_OS_Process *compute_wire_response; struct GNUNET_OS_Process *compute_wire_response;
struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CONFIGURATION_Handle *cfg;
struct GNUNET_GETOPT_CommandLineOption options[] = { struct GNUNET_GETOPT_CommandLineOption options[] = {
GNUNET_GETOPT_option_mandatory
GNUNET_GETOPT_option_cfgfile (GNUNET_GETOPT_option_cfgfile (&cfg_filename)),
(&cfg_filename), GNUNET_GETOPT_option_version (PACKAGE_VERSION " " VCS_VERSION),
GNUNET_GETOPT_option_help ("Exchange benchmark"),
GNUNET_GETOPT_option_version GNUNET_GETOPT_option_loglevel (&loglev),
(PACKAGE_VERSION " " VCS_VERSION), GNUNET_GETOPT_option_uint ('n',
GNUNET_GETOPT_option_help
("Exchange benchmark"),
GNUNET_GETOPT_option_loglevel
(&loglev),
GNUNET_GETOPT_option_uint
('n',
"coins-number", "coins-number",
"CN", "CN",
"How many coins we should instantiate", "How many coins we should instantiate",
&howmany_coins), &howmany_coins),
GNUNET_GETOPT_option_uint ('p',
GNUNET_GETOPT_option_string "parallelism",
('l', "NPROCS",
"How many client processes we should run",
&howmany_clients),
GNUNET_GETOPT_option_string ('l',
"logfile", "logfile",
"LF", "LF",
"will log to file LF", "will log to file LF",
&logfile), &logfile),
GNUNET_GETOPT_OPTION_END GNUNET_GETOPT_OPTION_END
}; };
if (GNUNET_SYSERR == (result = GNUNET_GETOPT_run unsetenv ("XDG_DATA_HOME");
("taler-exchange-benchmark", unsetenv ("XDG_CONFIG_HOME");
if (GNUNET_SYSERR ==
(result = GNUNET_GETOPT_run ("taler-exchange-benchmark",
options, options,
argc, argc,
argv))) argv)))
@ -512,27 +562,19 @@ main (int argc,
TALER_LOG_ERROR ("Unparsable CLI options\n"); TALER_LOG_ERROR ("Unparsable CLI options\n");
return BAD_CLI_ARG; return BAD_CLI_ARG;
} }
GNUNET_log_setup ("taler-exchange-benchmark", GNUNET_log_setup ("taler-exchange-benchmark",
NULL == loglev ? "INFO" : loglev, NULL == loglev ? "INFO" : loglev,
logfile); logfile);
if (NULL == cfg_filename)
{
TALER_LOG_ERROR ("-c option is mandatory\n");
return NO_CONFIG_FILE_GIVEN;
}
cfg = GNUNET_CONFIGURATION_create (); cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK != GNUNET_CONFIGURATION_load if (GNUNET_OK !=
(cfg, GNUNET_CONFIGURATION_load (cfg,
cfg_filename)) cfg_filename))
{ {
TALER_LOG_ERROR ("Could not parse configuration\n"); TALER_LOG_ERROR ("Could not parse configuration\n");
return BAD_CONFIG_FILE; return BAD_CONFIG_FILE;
} }
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string if (GNUNET_OK !=
(cfg, GNUNET_CONFIGURATION_get_value_string (cfg,
"taler", "taler",
"currency", "currency",
&currency)) &currency))
@ -543,6 +585,12 @@ main (int argc,
GNUNET_CONFIGURATION_destroy (cfg); GNUNET_CONFIGURATION_destroy (cfg);
return BAD_CONFIG_FILE; 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 *bank_details_section;
@ -582,21 +630,19 @@ main (int argc,
" is your PATH correct?\n"); " is your PATH correct?\n");
return GNUNET_NO; return GNUNET_NO;
} }
GNUNET_OS_process_wait GNUNET_OS_process_wait (compute_wire_response);
(compute_wire_response); GNUNET_OS_process_destroy (compute_wire_response);
GNUNET_OS_process_destroy
(compute_wire_response);
GNUNET_assert GNUNET_assert
/* Takes care of dropping all tables. */ /* Takes care of dropping all tables. */
(GNUNET_OK == TALER_TESTING_prepare_exchange (GNUNET_OK == TALER_TESTING_prepare_exchange
(cfg_filename, (cfg_filename,
&exchange_url)); // never used, we do all via handle. &exchange_url));
result = TALER_TESTING_setup_with_exchange result = parallel_benchmark (&run,
(run,
NULL, NULL,
cfg_filename); cfg_filename,
exchange_url);
GNUNET_free (exchange_url);
duration = GNUNET_TIME_absolute_get_duration (start_time); duration = GNUNET_TIME_absolute_get_duration (start_time);
TALER_LOG_INFO ("Executed W=%u, D=%u, R=%u, operations in %s\n", TALER_LOG_INFO ("Executed W=%u, D=%u, R=%u, operations in %s\n",
@ -605,7 +651,7 @@ main (int argc,
howmany_refreshes, howmany_refreshes,
GNUNET_STRINGS_relative_time_to_string GNUNET_STRINGS_relative_time_to_string
(duration, (duration,
GNUNET_YES)); GNUNET_NO));
return (GNUNET_OK == result) ? 0 : result; return (GNUNET_OK == result) ? 0 : result;
} }