h2load: Add option for user-definable rate period
This commit is contained in:
parent
e262c013bd
commit
afa14d36a8
|
@ -74,9 +74,9 @@ namespace h2load {
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: data_length(-1), addrs(nullptr), nreqs(1), nclients(1), nthreads(1),
|
: data_length(-1), addrs(nullptr), nreqs(1), nclients(1), nthreads(1),
|
||||||
max_concurrent_streams(-1), window_bits(30), connection_window_bits(30),
|
max_concurrent_streams(-1), window_bits(30), connection_window_bits(30),
|
||||||
rate(0), nconns(0), conn_active_timeout(0), conn_inactivity_timeout(0),
|
rate(0), rate_period(1.0), nconns(0), conn_active_timeout(0),
|
||||||
no_tls_proto(PROTO_HTTP2), data_fd(-1), port(0), default_port(0),
|
conn_inactivity_timeout(0), no_tls_proto(PROTO_HTTP2), data_fd(-1),
|
||||||
verbose(false), timing_script(false) {}
|
port(0), default_port(0), verbose(false), timing_script(false) {}
|
||||||
|
|
||||||
Config::~Config() {
|
Config::~Config() {
|
||||||
freeaddrinfo(addrs);
|
freeaddrinfo(addrs);
|
||||||
|
@ -136,8 +136,8 @@ void readcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Called every second when rate mode is being used
|
// Called every rate_period when rate mode is being used
|
||||||
void second_timeout_w_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
void rate_period_timeout_w_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
auto worker = static_cast<Worker *>(w->data);
|
auto worker = static_cast<Worker *>(w->data);
|
||||||
auto nclients_per_second = worker->rate;
|
auto nclients_per_second = worker->rate;
|
||||||
auto conns_remaining = worker->nclients - worker->nconns_made;
|
auto conns_remaining = worker->nclients - worker->nconns_made;
|
||||||
|
@ -938,8 +938,9 @@ Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients,
|
||||||
auto nreqs_per_client = req_todo / nclients;
|
auto nreqs_per_client = req_todo / nclients;
|
||||||
auto nreqs_rem = req_todo % nclients;
|
auto nreqs_rem = req_todo % nclients;
|
||||||
|
|
||||||
// create timer that will go off every second
|
// create timer that will go off every rate_period
|
||||||
ev_timer_init(&timeout_watcher, second_timeout_w_cb, 0., 1.);
|
ev_timer_init(&timeout_watcher, rate_period_timeout_w_cb, 0.,
|
||||||
|
config->rate_period);
|
||||||
timeout_watcher.data = this;
|
timeout_watcher.data = this;
|
||||||
|
|
||||||
if (!config->is_rate_mode()) {
|
if (!config->is_rate_mode()) {
|
||||||
|
@ -974,8 +975,8 @@ void Worker::run() {
|
||||||
} else {
|
} else {
|
||||||
ev_timer_again(loop, &timeout_watcher);
|
ev_timer_again(loop, &timeout_watcher);
|
||||||
|
|
||||||
// call callback so that we don't waste the first second
|
// call callback so that we don't waste the first rate_period
|
||||||
second_timeout_w_cb(loop, &timeout_watcher, 0);
|
rate_period_timeout_w_cb(loop, &timeout_watcher, 0);
|
||||||
}
|
}
|
||||||
ev_run(loop, 0);
|
ev_run(loop, 0);
|
||||||
}
|
}
|
||||||
|
@ -1345,9 +1346,16 @@ Options:
|
||||||
Specifies the fixed rate at which connections are
|
Specifies the fixed rate at which connections are
|
||||||
created. The rate must be a positive integer,
|
created. The rate must be a positive integer,
|
||||||
representing the number of connections to be made per
|
representing the number of connections to be made per
|
||||||
second. When the rate is 0, the program will run as it
|
rate period. When the rate is 0, the program will run as
|
||||||
normally does, creating connections at whatever variable
|
it normally does, creating connections at whatever
|
||||||
rate it wants. The default value for this option is 0.
|
variable rate it wants. The default value for this
|
||||||
|
option is 0.
|
||||||
|
--rate-period=<N>
|
||||||
|
Specifies the time period between creating connections.
|
||||||
|
The period must be a positive number greater than or
|
||||||
|
equal to 1.0, representing the length of the period in
|
||||||
|
seconds. This option is ignored if the rate option is
|
||||||
|
not used. The default value for this option is 1.0.
|
||||||
-C, --num-conns=<N>
|
-C, --num-conns=<N>
|
||||||
Specifies the total number of connections to create.
|
Specifies the total number of connections to create.
|
||||||
The total number of connections must be a positive
|
The total number of connections must be a positive
|
||||||
|
@ -1444,6 +1452,7 @@ int main(int argc, char **argv) {
|
||||||
{"timing-script-file", required_argument, &flag, 3},
|
{"timing-script-file", required_argument, &flag, 3},
|
||||||
{"base-uri", required_argument, nullptr, 'B'},
|
{"base-uri", required_argument, nullptr, 'B'},
|
||||||
{"npn-list", required_argument, &flag, 4},
|
{"npn-list", required_argument, &flag, 4},
|
||||||
|
{"rate-period", required_argument, &flag, 5},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
auto c = getopt_long(argc, argv, "hvW:c:d:m:n:p:t:w:H:i:r:C:T:N:B:",
|
auto c = getopt_long(argc, argv, "hvW:c:d:m:n:p:t:w:H:i:r:C:T:N:B:",
|
||||||
|
@ -1610,6 +1619,25 @@ int main(int argc, char **argv) {
|
||||||
// npn-list option
|
// npn-list option
|
||||||
config.npn_list = util::parse_config_str_list(optarg);
|
config.npn_list = util::parse_config_str_list(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 5: {
|
||||||
|
// rate-period
|
||||||
|
const char *start = optarg;
|
||||||
|
char *end;
|
||||||
|
errno = 0;
|
||||||
|
auto v = std::strtod(start, &end);
|
||||||
|
|
||||||
|
if (v < 1.0 || !std::isfinite(v) || end == start || errno != 0) {
|
||||||
|
auto error = errno;
|
||||||
|
std::cerr << "Rate period value error " << optarg << std::endl;
|
||||||
|
if (error != 0) {
|
||||||
|
std::cerr << "\n\t" << strerror(error) << std::endl;
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.rate_period = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1630,12 +1658,6 @@ int main(int argc, char **argv) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.timing_script && config.is_rate_mode()) {
|
|
||||||
std::cerr << "--timing-script, -r: these options cannot be used together."
|
|
||||||
<< std::endl;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.npn_list.empty()) {
|
if (config.npn_list.empty()) {
|
||||||
config.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST);
|
config.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST);
|
||||||
}
|
}
|
||||||
|
@ -1996,14 +2018,28 @@ int main(int argc, char **argv) {
|
||||||
if (!config.is_rate_mode()) {
|
if (!config.is_rate_mode()) {
|
||||||
nclients = nclients_per_thread + (nclients_rem-- > 0);
|
nclients = nclients_per_thread + (nclients_rem-- > 0);
|
||||||
nreqs = nreqs_per_thread + (nreqs_rem-- > 0);
|
nreqs = nreqs_per_thread + (nreqs_rem-- > 0);
|
||||||
|
|
||||||
|
std::cout << "spawning thread #" << i << ": " << nclients
|
||||||
|
<< " concurrent clients, " << nreqs << " total requests"
|
||||||
|
<< std::endl;
|
||||||
} else {
|
} else {
|
||||||
nclients = rate * seconds + nclients_extra_per_thread +
|
nclients = rate * seconds + nclients_extra_per_thread +
|
||||||
(nclients_extra_per_thread_rem-- > 0);
|
(nclients_extra_per_thread_rem-- > 0);
|
||||||
nreqs = nclients * config.max_concurrent_streams;
|
nreqs = nclients * config.max_concurrent_streams;
|
||||||
|
|
||||||
|
std::stringstream rate_report;
|
||||||
|
if (nclients >= config.rate) {
|
||||||
|
rate_report << "Up to " << config.rate
|
||||||
|
<< " client(s) will be created every "
|
||||||
|
<< std::setprecision(3) << config.rate_period
|
||||||
|
<< " seconds. ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "spawning thread #" << i << ": " << nclients
|
std::cout << "spawning thread #" << i << ": " << nclients
|
||||||
<< " concurrent clients, " << nreqs << " total requests"
|
<< " total client(s). " << rate_report.str() << nreqs
|
||||||
<< std::endl;
|
<< " total requests" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
workers.push_back(
|
workers.push_back(
|
||||||
make_unique<Worker>(i, ssl_ctx, nreqs, nclients, rate, &config));
|
make_unique<Worker>(i, ssl_ctx, nreqs, nclients, rate, &config));
|
||||||
auto &worker = workers.back();
|
auto &worker = workers.back();
|
||||||
|
@ -2018,14 +2054,27 @@ int main(int argc, char **argv) {
|
||||||
if (!config.is_rate_mode()) {
|
if (!config.is_rate_mode()) {
|
||||||
nclients_last = nclients_per_thread + (nclients_rem-- > 0);
|
nclients_last = nclients_per_thread + (nclients_rem-- > 0);
|
||||||
nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0);
|
nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0);
|
||||||
|
|
||||||
|
std::cout << "spawning thread #" << (config.nthreads - 1) << ": "
|
||||||
|
<< nclients_last << " concurrent clients, " << nreqs_last
|
||||||
|
<< " total requests" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
nclients_last = rate_last * seconds + nclients_extra_per_thread +
|
nclients_last = rate_last * seconds + nclients_extra_per_thread +
|
||||||
(nclients_extra_per_thread_rem-- > 0);
|
(nclients_extra_per_thread_rem-- > 0);
|
||||||
nreqs_last = nclients_last * config.max_concurrent_streams;
|
nreqs_last = nclients_last * config.max_concurrent_streams;
|
||||||
|
|
||||||
|
std::stringstream rate_report;
|
||||||
|
if (nclients_last >= config.rate) {
|
||||||
|
rate_report << "Up to " << config.rate
|
||||||
|
<< " client(s) will be created every " << std::setprecision(3)
|
||||||
|
<< config.rate_period << " seconds. ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "spawning thread #" << (config.nthreads - 1) << ": "
|
std::cout << "spawning thread #" << (config.nthreads - 1) << ": "
|
||||||
<< nclients_last << " concurrent clients, " << nreqs_last
|
<< nclients_last << " total client(s). " << rate_report.str()
|
||||||
<< " total requests" << std::endl;
|
<< nreqs_last << " total requests" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
workers.push_back(make_unique<Worker>(config.nthreads - 1, ssl_ctx,
|
workers.push_back(make_unique<Worker>(config.nthreads - 1, ssl_ctx,
|
||||||
nreqs_last, nclients_last, rate_last,
|
nreqs_last, nclients_last, rate_last,
|
||||||
&config));
|
&config));
|
||||||
|
|
|
@ -81,6 +81,7 @@ struct Config {
|
||||||
size_t connection_window_bits;
|
size_t connection_window_bits;
|
||||||
// rate at which connections should be made
|
// rate at which connections should be made
|
||||||
size_t rate;
|
size_t rate;
|
||||||
|
ev_tstamp rate_period;
|
||||||
// number of connections made
|
// number of connections made
|
||||||
size_t nconns;
|
size_t nconns;
|
||||||
// amount of time to wait for activity on a given connection
|
// amount of time to wait for activity on a given connection
|
||||||
|
|
Loading…
Reference in New Issue