From 52152ad96d73c8ec839f8b56010c26e20f6b7ed1 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Tue, 21 Jul 2015 11:06:33 -0700 Subject: [PATCH 01/12] Can make h2load, but running into recursive loop problem --- src/h2load.cc | 198 +++++++++++++++++++++++--------------------------- src/h2load.h | 1 + 2 files changed, 91 insertions(+), 108 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index b1f5a672..014985e2 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -154,6 +154,34 @@ void readcb(struct ev_loop *loop, ev_io *w, int revents) { } } // namespace +namespace { +// Called every second when rate mode is being used +void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { + auto worker = static_cast(w->data); + auto nclients_per_second = worker->config->rate; + auto nclients = std::min(nclients_per_second, worker->nclients - worker->nconns_made); + + for (ssize_t i = 0; i < worker->nclients; ++i) { + auto req_todo = worker->nreqs_per_client; + if (worker->nreqs_rem > 0) { + ++req_todo; + --worker->nreqs_rem; + } + worker->clients.push_back(make_unique(worker, req_todo)); + auto &client = worker->clients.back(); + if (client->connect() != 0) { + std::cerr << "client could not connect to host" << std::endl; + client->fail(); + } + ++worker->nconns_made; + } + if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds - 1))) { + ev_timer_stop(worker->rate_loop, w); + } + ++worker->current_second; +} +} // namespace + Client::Client(Worker *worker, size_t req_todo) : worker(worker), ssl(nullptr), next_addr(config.addrs), reqidx(0), state(CLIENT_IDLE), first_byte_received(false), req_todo(req_todo), @@ -706,20 +734,28 @@ void Client::signal_write() { ev_io_start(worker->loop, &wev); } Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, Config *config) : stats(req_todo), loop(ev_loop_new(0)), ssl_ctx(ssl_ctx), config(config), - id(id), tls_info_report_done(false) { + id(id), tls_info_report_done(false), rate_loop(EV_DEFAULT), nconns_made(0), nclients(nclients) { stats.req_todo = req_todo; progress_interval = std::max((size_t)1, req_todo / 10); + nreqs_per_client = req_todo / nclients; + nreqs_rem = req_todo % nclients; - auto nreqs_per_client = req_todo / nclients; - auto nreqs_rem = req_todo % nclients; - - for (size_t i = 0; i < nclients; ++i) { - auto req_todo = nreqs_per_client; - if (nreqs_rem > 0) { - ++req_todo; - --nreqs_rem; + if (config->is_rate_mode()) { + // create timer that will go off every second + ev_timer timeout_watcher; + timeout_watcher.data = this; + ev_init(&timeout_watcher, second_timeout_w_cb); + timeout_watcher.repeat = 1.; + ev_timer_again(rate_loop, &timeout_watcher); + } else { + for (size_t i = 0; i < nclients; ++i) { + auto req_todo = nreqs_per_client; + if (nreqs_rem > 0) { + ++req_todo; + --nreqs_rem; + } + clients.push_back(make_unique(this, req_todo)); } - clients.push_back(make_unique(this, req_todo)); } } @@ -731,11 +767,15 @@ Worker::~Worker() { } void Worker::run() { - for (auto &client : clients) { - if (client->connect() != 0) { - std::cerr << "client could not connect to host" << std::endl; - client->fail(); + if (!config->is_rate_mode()) { + for (auto &client : clients) { + if (client->connect() != 0) { + std::cerr << "client could not connect to host" << std::endl; + client->fail(); + } } + } else { + ev_run(rate_loop, 0); } ev_run(loop, 0); } @@ -964,31 +1004,6 @@ std::vector read_uri_from_file(std::istream &infile) { } } // namespace -namespace { -// Called every second when rate mode is being used -void second_timeout_cb(EV_P_ ev_timer *w, int revents) { - auto config = static_cast(w->data); - - auto nclients_per_worker = config->rate; - auto nreqs_per_worker = config->max_concurrent_streams * config->rate; - - if (config->current_worker >= std::max((ssize_t)0, (config->seconds - 1))) { - nclients_per_worker = config->rate + config->conns_remainder; - nreqs_per_worker = (int)config->max_concurrent_streams * - (config->rate + config->conns_remainder); - ev_timer_stop(config->rate_loop, w); - } - - config->workers.push_back( - make_unique(config->current_worker, config->ssl_ctx, - nreqs_per_worker, nclients_per_worker, config)); - - config->current_worker++; - - config->workers.back()->run(); -} -} // namespace - namespace { void print_version(std::ostream &out) { out << "h2load nghttp2/" NGHTTP2_VERSION << std::endl; @@ -1432,6 +1447,7 @@ int main(int argc, char **argv) { std::cerr << "The test will create " << (config.max_concurrent_streams * config.nconns) << " total requests." << std::endl; + config.nreqs = config.max_concurrent_streams * config.nconns; } else { std::cout << "-C, -n: warning: number of requests conflict. " << std::endl; @@ -1441,6 +1457,7 @@ int main(int argc, char **argv) { config.nreqs, (size_t)(config.max_concurrent_streams * config.nconns)) << " total requests." << std::endl; + config.nreqs = std::min(config.nreqs, (size_t)(config.max_concurrent_streams * config.nreqs)); } } @@ -1519,85 +1536,50 @@ int main(int argc, char **argv) { size_t nclients_per_thread = config.nclients / config.nthreads; ssize_t nclients_rem = config.nclients % config.nthreads; + // In rate mode, we want each Worker to create a total of + // C/t connections. + if (config.is_rate_mode()) { + nclients_per_thread = config.nconns / (ssize_t)config.nthreads; + nclients_rem = config.nconns % (ssize_t)config.nthreads; + std::cout << "nclients_per_thread: " << nclients_per_thread << std::endl; + std::cout << "nclients_rem :" << nclients_rem << std::endl; + } + std::cout << "starting benchmark..." << std::endl; auto start = std::chrono::steady_clock::now(); - // if not in rate mode, continue making workers and clients normally - if (!config.is_rate_mode()) { - config.workers.reserve(config.nthreads); + config.workers.reserve(config.nthreads); #ifndef NOTHREADS - std::vector> futures; - for (size_t i = 0; i < config.nthreads - 1; ++i) { - auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); - auto nclients = nclients_per_thread + (nclients_rem-- > 0); - std::cout << "spawning thread #" << i << ": " << nclients - << " concurrent clients, " << nreqs << " total requests" - << std::endl; - config.workers.push_back( - make_unique(i, ssl_ctx, nreqs, nclients, &config)); - auto &worker = config.workers.back(); - futures.push_back( - std::async(std::launch::async, [&worker]() { worker->run(); })); - } + std::vector> futures; + for (size_t i = 0; i < config.nthreads - 1; ++i) { + auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); + auto nclients = nclients_per_thread + (nclients_rem-- > 0); + std::cout << "spawning thread #" << i << ": " << nclients + << " concurrent clients, " << nreqs << " total requests" + << std::endl; + config.workers.push_back( + make_unique(i, ssl_ctx, nreqs, nclients, &config)); + auto &worker = config.workers.back(); + futures.push_back( + std::async(std::launch::async, [&worker]() { worker->run(); })); + } #endif // NOTHREADS - auto nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0); - auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); - std::cout << "spawning thread #" << (config.nthreads - 1) << ": " - << nclients_last << " concurrent clients, " << nreqs_last - << " total requests" << std::endl; - config.workers.push_back(make_unique( - config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, &config)); - config.workers.back()->run(); + auto nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0); + auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); + std::cout << "spawning thread #" << (config.nthreads - 1) << ": " + << nclients_last << " concurrent clients, " << nreqs_last + << " total requests" << std::endl; + config.workers.push_back(make_unique( + config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, &config)); + config.workers.back()->run(); #ifndef NOTHREADS - for (auto &fut : futures) { - fut.get(); - } + for (auto &fut : futures) { + fut.get(); + } #endif // NOTHREADS - } //! config.is_rate_mode() - // if in rate mode, create a new worker each second - else { - // set various config values - if ((int)config.nreqs < config.nconns) { - config.seconds = c_time; - } else if (config.nconns == 0) { - config.seconds = n_time; - } else { - config.seconds = std::min(n_time, c_time); - } - config.workers.reserve(config.seconds); - - config.conns_remainder = config.nconns % config.rate; - - // config.seconds must be positive or else an exception is thrown - if (config.seconds <= 0) { - std::cerr << "Test cannot be run with current option values." - << " Please look at documentation for -r option for" - << " more information." << std::endl; - exit(EXIT_FAILURE); - } - config.current_worker = 0; - - config.ssl_ctx = ssl_ctx; - - // create timer that will go off every second - ev_timer timeout_watcher; - - // create loop for running the timer - struct ev_loop *rate_loop = EV_DEFAULT; - - config.rate_loop = rate_loop; - - // giving the second_timeout_cb access to config - timeout_watcher.data = &config; - - ev_init(&timeout_watcher, second_timeout_cb); - timeout_watcher.repeat = 1.; - ev_timer_again(rate_loop, &timeout_watcher); - ev_run(rate_loop, 0); - } // end rate mode section auto end = std::chrono::steady_clock::now(); auto duration = diff --git a/src/h2load.h b/src/h2load.h index 986bf78c..b71d2263 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -184,6 +184,7 @@ struct Worker { size_t progress_interval; uint32_t id; bool tls_info_report_done; + struct ev_loop *rate_loop; Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, Config *config); From 650e463a4971aa591b8844fbd23189ab6a5913df Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Tue, 21 Jul 2015 11:28:12 -0700 Subject: [PATCH 02/12] First try with something working, still need to clean and test --- src/h2load.cc | 7 +++---- src/h2load.h | 6 ++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 014985e2..2cff0e61 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -176,7 +176,7 @@ void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { ++worker->nconns_made; } if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds - 1))) { - ev_timer_stop(worker->rate_loop, w); + ev_timer_stop(worker->loop, w); } ++worker->current_second; } @@ -742,11 +742,10 @@ Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, if (config->is_rate_mode()) { // create timer that will go off every second - ev_timer timeout_watcher; + //ev_timer timeout_watcher; timeout_watcher.data = this; ev_init(&timeout_watcher, second_timeout_w_cb); timeout_watcher.repeat = 1.; - ev_timer_again(rate_loop, &timeout_watcher); } else { for (size_t i = 0; i < nclients; ++i) { auto req_todo = nreqs_per_client; @@ -775,7 +774,7 @@ void Worker::run() { } } } else { - ev_run(rate_loop, 0); + ev_timer_again(loop, &timeout_watcher); } ev_run(loop, 0); } diff --git a/src/h2load.h b/src/h2load.h index b71d2263..06e13b1b 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -185,6 +185,12 @@ struct Worker { uint32_t id; bool tls_info_report_done; struct ev_loop *rate_loop; + ssize_t current_second; + ssize_t nconns_made; + ssize_t nclients; + ssize_t nreqs_per_client; + ssize_t nreqs_rem; + ev_timer timeout_watcher; Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, Config *config); From 916e27489f7ea9f4f7fa5d6fe478b276b8575e92 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Tue, 21 Jul 2015 16:53:46 -0700 Subject: [PATCH 03/12] rate now working --- src/h2load.cc | 65 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 2cff0e61..4562c482 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -157,16 +157,23 @@ void readcb(struct ev_loop *loop, ev_io *w, int revents) { namespace { // Called every second when rate mode is being used void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { + //TODO + std::cout << "seconf_timeout_w_cb" << std::endl; auto worker = static_cast(w->data); - auto nclients_per_second = worker->config->rate; + auto nclients_per_second = worker->rate; auto nclients = std::min(nclients_per_second, worker->nclients - worker->nconns_made); - for (ssize_t i = 0; i < worker->nclients; ++i) { + std::cout << "worker rate: " << worker->rate << std::endl; + std::cout << "nclients- nconns_made = " << worker->nclients - worker->nconns_made << std::endl; + + std::cout << "nclients: " << nclients << std::endl; + for (ssize_t i = 0; i < nclients; ++i) { auto req_todo = worker->nreqs_per_client; if (worker->nreqs_rem > 0) { ++req_todo; --worker->nreqs_rem; } + std::cout << "i: " << i << "req_todo: " << req_todo << std::endl; worker->clients.push_back(make_unique(worker, req_todo)); auto &client = worker->clients.back(); if (client->connect() != 0) { @@ -176,6 +183,9 @@ void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { ++worker->nconns_made; } if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds - 1))) { + std::cout << "worker->current_second: " << worker->current_second << std::endl; + std::cout << "worker->config->seconds: " << worker->config->seconds << std::endl; + std::cout << "ev_timer_stop" << std::endl; ev_timer_stop(worker->loop, w); } ++worker->current_second; @@ -732,14 +742,16 @@ void Client::record_ttfb(Stats *stat) { void Client::signal_write() { ev_io_start(worker->loop, &wev); } Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, - Config *config) + ssize_t rate, Config *config) : stats(req_todo), loop(ev_loop_new(0)), ssl_ctx(ssl_ctx), config(config), - id(id), tls_info_report_done(false), rate_loop(EV_DEFAULT), nconns_made(0), nclients(nclients) { + id(id), tls_info_report_done(false), rate_loop(EV_DEFAULT), current_second(0), nconns_made(0), nclients(nclients), rate(rate) { stats.req_todo = req_todo; progress_interval = std::max((size_t)1, req_todo / 10); nreqs_per_client = req_todo / nclients; nreqs_rem = req_todo % nclients; + std::cout << "NREQS_PER_CLIENT: " << nreqs_per_client << std::endl; + std::cout << "NCLIENTS (in Worker): " << this->nclients << std::endl; if (config->is_rate_mode()) { // create timer that will go off every second //ev_timer timeout_watcher; @@ -1301,13 +1313,13 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - if (config.nreqs < config.nclients) { + if (!config.is_rate_mode() && config.nreqs < config.nclients) { std::cerr << "-n, -c: the number of requests must be greater than or " << "equal to the concurrent clients." << std::endl; exit(EXIT_FAILURE); } - if (config.nclients < config.nthreads) { + if (!config.is_rate_mode() && config.nclients < config.nthreads) { std::cerr << "-c, -t: the number of client must be greater than or equal " "to the number of threads." << std::endl; exit(EXIT_FAILURE); @@ -1431,6 +1443,8 @@ int main(int argc, char **argv) { ssize_t n_time = 0; ssize_t c_time = 0; + size_t actual_nreqs = config.nreqs; + std::cout << "max_concurrent_streams: " << config.max_concurrent_streams << std::endl; // only care about n_time and c_time in rate mode if (config.is_rate_mode() && config.max_concurrent_streams != 0) { n_time = (int)config.nreqs / @@ -1446,7 +1460,7 @@ int main(int argc, char **argv) { std::cerr << "The test will create " << (config.max_concurrent_streams * config.nconns) << " total requests." << std::endl; - config.nreqs = config.max_concurrent_streams * config.nconns; + actual_nreqs = config.max_concurrent_streams * config.nconns; } else { std::cout << "-C, -n: warning: number of requests conflict. " << std::endl; @@ -1456,7 +1470,12 @@ int main(int argc, char **argv) { config.nreqs, (size_t)(config.max_concurrent_streams * config.nconns)) << " total requests." << std::endl; - config.nreqs = std::min(config.nreqs, (size_t)(config.max_concurrent_streams * config.nreqs)); + actual_nreqs = std::min(config.nreqs, (size_t)(config.max_concurrent_streams * config.nreqs)); + } + } else { + if (config.is_rate_mode() && config.max_concurrent_streams != 0 && + (n_time != c_time) && config.nreqs == 1 && config.nconns != 0) { + actual_nreqs = config.max_concurrent_streams * config.nconns; } } @@ -1525,16 +1544,32 @@ int main(int argc, char **argv) { resolve_host(); - if (config.nclients == 1) { + if (!config.is_rate_mode() && config.nclients == 1) { config.nthreads = 1; } + if (config.is_rate_mode()) { + + // set various config values + if ((int)config.nreqs < config.nconns) { + config.seconds = c_time; + } else if (config.nconns == 0) { + config.seconds = n_time; + } else { + config.seconds = std::min(n_time, c_time); + } + config.nreqs = actual_nreqs; + } + size_t nreqs_per_thread = config.nreqs / config.nthreads; ssize_t nreqs_rem = config.nreqs % config.nthreads; size_t nclients_per_thread = config.nclients / config.nthreads; ssize_t nclients_rem = config.nclients % config.nthreads; + size_t rate_per_thread = config.rate / config.nthreads; + ssize_t rate_per_thread_rem = config.rate % config.nthreads; + // In rate mode, we want each Worker to create a total of // C/t connections. if (config.is_rate_mode()) { @@ -1542,6 +1577,12 @@ int main(int argc, char **argv) { nclients_rem = config.nconns % (ssize_t)config.nthreads; std::cout << "nclients_per_thread: " << nclients_per_thread << std::endl; std::cout << "nclients_rem :" << nclients_rem << std::endl; + std::cout << "SECONDS " << config.seconds << std::endl; + std::cout << "NREQS " << config.nreqs << std::endl; + std::cout << "N_TIME " << n_time << std::endl; + std::cout << "C_TIME " << c_time << std::endl; + + std::cout << "nreqs_per_thread" << nreqs_per_thread << std::endl; } std::cout << "starting benchmark..." << std::endl; @@ -1554,11 +1595,12 @@ int main(int argc, char **argv) { for (size_t i = 0; i < config.nthreads - 1; ++i) { auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); auto nclients = nclients_per_thread + (nclients_rem-- > 0); + auto rate = rate_per_thread + (rate_per_thread_rem-- > 0); std::cout << "spawning thread #" << i << ": " << nclients << " concurrent clients, " << nreqs << " total requests" << std::endl; config.workers.push_back( - make_unique(i, ssl_ctx, nreqs, nclients, &config)); + make_unique(i, ssl_ctx, nreqs, nclients, rate, &config)); auto &worker = config.workers.back(); futures.push_back( std::async(std::launch::async, [&worker]() { worker->run(); })); @@ -1567,11 +1609,12 @@ int main(int argc, char **argv) { auto nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0); auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); + auto rate_last = rate_per_thread + (rate_per_thread_rem-- > 0); std::cout << "spawning thread #" << (config.nthreads - 1) << ": " << nclients_last << " concurrent clients, " << nreqs_last << " total requests" << std::endl; config.workers.push_back(make_unique( - config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, &config)); + config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, rate_last, &config)); config.workers.back()->run(); #ifndef NOTHREADS From 65df3c63bf6c884ceffa5886ac4605997cded6c3 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Wed, 22 Jul 2015 16:41:58 -0700 Subject: [PATCH 04/12] Adding new rate and connection allocation to threads --- src/h2load.cc | 48 ++++++++++++++++++++++++++++-------------------- src/h2load.h | 3 ++- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 4562c482..f56f6bbb 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -158,22 +158,23 @@ namespace { // Called every second when rate mode is being used void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { //TODO - std::cout << "seconf_timeout_w_cb" << std::endl; + //std::cout << "seconf_timeout_w_cb" << std::endl; auto worker = static_cast(w->data); auto nclients_per_second = worker->rate; - auto nclients = std::min(nclients_per_second, worker->nclients - worker->nconns_made); + auto conns_remaining = worker->nclients - worker->nconns_made; + auto nclients = std::min(nclients_per_second, conns_remaining); - std::cout << "worker rate: " << worker->rate << std::endl; - std::cout << "nclients- nconns_made = " << worker->nclients - worker->nconns_made << std::endl; + if (nclients_per_second > conns_remaining) { + nclients += conns_remaining; + } - std::cout << "nclients: " << nclients << std::endl; + std::cout << "worker: " << worker->id << " rate: " << worker->rate << std::endl; + //std::cout << "nclients- nconns_made = " << worker->nclients - worker->nconns_made << std::endl; + + std::cout << "worker: " << worker->id << " nclients: " << nclients << std::endl; for (ssize_t i = 0; i < nclients; ++i) { - auto req_todo = worker->nreqs_per_client; - if (worker->nreqs_rem > 0) { - ++req_todo; - --worker->nreqs_rem; - } - std::cout << "i: " << i << "req_todo: " << req_todo << std::endl; + auto req_todo = worker->config->max_concurrent_streams; + std::cout << "worker: " << worker->id << " i: " << i << "req_todo: " << req_todo << std::endl; worker->clients.push_back(make_unique(worker, req_todo)); auto &client = worker->clients.back(); if (client->connect() != 0) { @@ -182,10 +183,11 @@ void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { } ++worker->nconns_made; } - if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds - 1))) { - std::cout << "worker->current_second: " << worker->current_second << std::endl; - std::cout << "worker->config->seconds: " << worker->config->seconds << std::endl; - std::cout << "ev_timer_stop" << std::endl; + //if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds))) { + if (worker->nconns_made >= worker->nclients) { + std::cout << "worker: " << worker->id << " worker->current_second: " << worker->current_second << std::endl; + std::cout << "worker: " << worker->id << " worker->config->seconds: " << worker->config->seconds << std::endl; + //std::cout << "ev_timer_stop" << std::endl; ev_timer_stop(worker->loop, w); } ++worker->current_second; @@ -1570,13 +1572,19 @@ int main(int argc, char **argv) { size_t rate_per_thread = config.rate / config.nthreads; ssize_t rate_per_thread_rem = config.rate % config.nthreads; + auto nclients_extra = 0; + auto nclients_extra_per_thread = 0; + auto nclients_extra_rem_per_thread = 0; // In rate mode, we want each Worker to create a total of // C/t connections. if (config.is_rate_mode()) { - nclients_per_thread = config.nconns / (ssize_t)config.nthreads; - nclients_rem = config.nconns % (ssize_t)config.nthreads; - std::cout << "nclients_per_thread: " << nclients_per_thread << std::endl; - std::cout << "nclients_rem :" << nclients_rem << std::endl; + nclients_extra = config.nconns - (config.seconds * config.rate); + nclients_extra_per_thread = nclients_extra / (ssize_t)config.nthreads; + nclients_extra_rem_per_thread = (ssize_t)nclients_extra % (ssize_t)config.nthreads; + + std::cout << "nclients_extra: " << nclients_extra << std::endl; + std::cout << "nclients_extra_per_thread: " << nclients_extra_per_thread << std::endl; + std::cout << "nclients_extra_rem_per_thread: " << nclients_extra_rem_per_thread << std::endl; std::cout << "SECONDS " << config.seconds << std::endl; std::cout << "NREQS " << config.nreqs << std::endl; std::cout << "N_TIME " << n_time << std::endl; @@ -1594,8 +1602,8 @@ int main(int argc, char **argv) { std::vector> futures; for (size_t i = 0; i < config.nthreads - 1; ++i) { auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); - auto nclients = nclients_per_thread + (nclients_rem-- > 0); auto rate = rate_per_thread + (rate_per_thread_rem-- > 0); + auto nclients = rate * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread--); std::cout << "spawning thread #" << i << ": " << nclients << " concurrent clients, " << nreqs << " total requests" << std::endl; diff --git a/src/h2load.h b/src/h2load.h index 06e13b1b..865f2b8f 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -191,8 +191,9 @@ struct Worker { ssize_t nreqs_per_client; ssize_t nreqs_rem; ev_timer timeout_watcher; + ssize_t rate; - Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, + Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, ssize_t rate, Config *config); ~Worker(); Worker(Worker &&o) = default; From 30235f88090d08bc48a7c5e65b59061f113d69be Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Thu, 23 Jul 2015 09:37:44 -0700 Subject: [PATCH 05/12] Assigning clients to workers proportional to rate --- src/h2load.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index f56f6bbb..a14fcffa 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -1569,8 +1569,8 @@ int main(int argc, char **argv) { size_t nclients_per_thread = config.nclients / config.nthreads; ssize_t nclients_rem = config.nclients % config.nthreads; - size_t rate_per_thread = config.rate / config.nthreads; - ssize_t rate_per_thread_rem = config.rate % config.nthreads; + size_t rate_per_thread = config.rate / (ssize_t)config.nthreads; + ssize_t rate_per_thread_rem = config.rate % (ssize_t)config.nthreads; auto nclients_extra = 0; auto nclients_extra_per_thread = 0; @@ -1603,7 +1603,11 @@ int main(int argc, char **argv) { for (size_t i = 0; i < config.nthreads - 1; ++i) { auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); auto rate = rate_per_thread + (rate_per_thread_rem-- > 0); - auto nclients = rate * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread--); + std::cout << "worker: " << i << "nclients_extra_per_thread: " << nclients_extra_per_thread << std::endl; + std::cout << "worker: " << i << "nclients_extra_rem_per_thread: " << nclients_extra_rem_per_thread << std::endl; + std::cout << "worker: " << i << "config.seconds: " << config.seconds << std::endl; + std::cout << "worker: " << i << "rate: " << rate << std::endl; + auto nclients = rate * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); std::cout << "spawning thread #" << i << ": " << nclients << " concurrent clients, " << nreqs << " total requests" << std::endl; @@ -1615,9 +1619,15 @@ int main(int argc, char **argv) { } #endif // NOTHREADS + std::cout << "worker: " << config.nthreads - 1 << "nclients_extra_per_thread: " << nclients_extra_per_thread << std::endl; + std::cout << "worker: " << config.nthreads - 1 << "nclients_extra_rem_per_thread: " << nclients_extra_rem_per_thread << std::endl; + std::cout << "worker: " << config.nthreads - 1 << "config.seconds: " << config.seconds << std::endl; auto nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0); auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); auto rate_last = rate_per_thread + (rate_per_thread_rem-- > 0); + if (config.is_rate_mode()) { + nclients_last = rate_last * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + } std::cout << "spawning thread #" << (config.nthreads - 1) << ": " << nclients_last << " concurrent clients, " << nreqs_last << " total requests" << std::endl; From 8325c6ccdf931dfac67ab6cd06793fb00accfb2e Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Thu, 23 Jul 2015 10:20:18 -0700 Subject: [PATCH 06/12] setting request number correctly: --- src/h2load.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index a14fcffa..be9c2567 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -160,18 +160,20 @@ void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { //TODO //std::cout << "seconf_timeout_w_cb" << std::endl; auto worker = static_cast(w->data); + std::cout << "worker: " << worker->id << " current_second: " << worker->current_second << std::endl; auto nclients_per_second = worker->rate; auto conns_remaining = worker->nclients - worker->nconns_made; auto nclients = std::min(nclients_per_second, conns_remaining); if (nclients_per_second > conns_remaining) { - nclients += conns_remaining; + //nclients += conns_remaining; } - std::cout << "worker: " << worker->id << " rate: " << worker->rate << std::endl; - //std::cout << "nclients- nconns_made = " << worker->nclients - worker->nconns_made << std::endl; + //std::cout << "worker: " << worker->id << " rate: " << worker->rate << std::endl; + std::cout << "worker: " << worker->id << " nclients - nconns_made = " << worker->nclients - worker->nconns_made << std::endl; - std::cout << "worker: " << worker->id << " nclients: " << nclients << std::endl; + std::cout << "worker: " << worker->id << " nclients: " << nclients << std::endl; + std::cout << "worker: " << worker->id << " nconns_made: " << worker->nconns_made << std::endl; for (ssize_t i = 0; i < nclients; ++i) { auto req_todo = worker->config->max_concurrent_streams; std::cout << "worker: " << worker->id << " i: " << i << "req_todo: " << req_todo << std::endl; @@ -183,7 +185,7 @@ void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { } ++worker->nconns_made; } - //if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds))) { + //if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds - 1))) { if (worker->nconns_made >= worker->nclients) { std::cout << "worker: " << worker->id << " worker->current_second: " << worker->current_second << std::endl; std::cout << "worker: " << worker->id << " worker->config->seconds: " << worker->config->seconds << std::endl; @@ -1603,11 +1605,11 @@ int main(int argc, char **argv) { for (size_t i = 0; i < config.nthreads - 1; ++i) { auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); auto rate = rate_per_thread + (rate_per_thread_rem-- > 0); - std::cout << "worker: " << i << "nclients_extra_per_thread: " << nclients_extra_per_thread << std::endl; - std::cout << "worker: " << i << "nclients_extra_rem_per_thread: " << nclients_extra_rem_per_thread << std::endl; - std::cout << "worker: " << i << "config.seconds: " << config.seconds << std::endl; - std::cout << "worker: " << i << "rate: " << rate << std::endl; - auto nclients = rate * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + auto nclients = nclients_per_thread + (nclients_rem-- > 0); + if (config.is_rate_mode()) { + nclients = rate * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + nreqs = nclients * config.max_concurrent_streams; + } std::cout << "spawning thread #" << i << ": " << nclients << " concurrent clients, " << nreqs << " total requests" << std::endl; @@ -1619,14 +1621,12 @@ int main(int argc, char **argv) { } #endif // NOTHREADS - std::cout << "worker: " << config.nthreads - 1 << "nclients_extra_per_thread: " << nclients_extra_per_thread << std::endl; - std::cout << "worker: " << config.nthreads - 1 << "nclients_extra_rem_per_thread: " << nclients_extra_rem_per_thread << std::endl; - std::cout << "worker: " << config.nthreads - 1 << "config.seconds: " << config.seconds << std::endl; auto nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0); auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); auto rate_last = rate_per_thread + (rate_per_thread_rem-- > 0); if (config.is_rate_mode()) { nclients_last = rate_last * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + nreqs_last = nclients_last * config.max_concurrent_streams; } std::cout << "spawning thread #" << (config.nthreads - 1) << ": " << nclients_last << " concurrent clients, " << nreqs_last From a04c67bcd68d5b30e558c9cb35ce634e9a3c130d Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Thu, 23 Jul 2015 10:30:55 -0700 Subject: [PATCH 07/12] Getting rid of print statements --- src/h2load.cc | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index be9c2567..4ead6d29 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -157,26 +157,13 @@ void readcb(struct ev_loop *loop, ev_io *w, int revents) { namespace { // Called every second when rate mode is being used void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { - //TODO - //std::cout << "seconf_timeout_w_cb" << std::endl; auto worker = static_cast(w->data); - std::cout << "worker: " << worker->id << " current_second: " << worker->current_second << std::endl; auto nclients_per_second = worker->rate; auto conns_remaining = worker->nclients - worker->nconns_made; auto nclients = std::min(nclients_per_second, conns_remaining); - if (nclients_per_second > conns_remaining) { - //nclients += conns_remaining; - } - - //std::cout << "worker: " << worker->id << " rate: " << worker->rate << std::endl; - std::cout << "worker: " << worker->id << " nclients - nconns_made = " << worker->nclients - worker->nconns_made << std::endl; - - std::cout << "worker: " << worker->id << " nclients: " << nclients << std::endl; - std::cout << "worker: " << worker->id << " nconns_made: " << worker->nconns_made << std::endl; for (ssize_t i = 0; i < nclients; ++i) { auto req_todo = worker->config->max_concurrent_streams; - std::cout << "worker: " << worker->id << " i: " << i << "req_todo: " << req_todo << std::endl; worker->clients.push_back(make_unique(worker, req_todo)); auto &client = worker->clients.back(); if (client->connect() != 0) { @@ -185,11 +172,7 @@ void second_timeout_w_cb(EV_P_ ev_timer *w, int revents) { } ++worker->nconns_made; } - //if (worker->current_second >= std::max((ssize_t)0, (worker->config->seconds - 1))) { if (worker->nconns_made >= worker->nclients) { - std::cout << "worker: " << worker->id << " worker->current_second: " << worker->current_second << std::endl; - std::cout << "worker: " << worker->id << " worker->config->seconds: " << worker->config->seconds << std::endl; - //std::cout << "ev_timer_stop" << std::endl; ev_timer_stop(worker->loop, w); } ++worker->current_second; @@ -754,11 +737,8 @@ Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, nreqs_per_client = req_todo / nclients; nreqs_rem = req_todo % nclients; - std::cout << "NREQS_PER_CLIENT: " << nreqs_per_client << std::endl; - std::cout << "NCLIENTS (in Worker): " << this->nclients << std::endl; if (config->is_rate_mode()) { // create timer that will go off every second - //ev_timer timeout_watcher; timeout_watcher.data = this; ev_init(&timeout_watcher, second_timeout_w_cb); timeout_watcher.repeat = 1.; @@ -1448,7 +1428,6 @@ int main(int argc, char **argv) { ssize_t n_time = 0; ssize_t c_time = 0; size_t actual_nreqs = config.nreqs; - std::cout << "max_concurrent_streams: " << config.max_concurrent_streams << std::endl; // only care about n_time and c_time in rate mode if (config.is_rate_mode() && config.max_concurrent_streams != 0) { n_time = (int)config.nreqs / @@ -1583,16 +1562,6 @@ int main(int argc, char **argv) { nclients_extra = config.nconns - (config.seconds * config.rate); nclients_extra_per_thread = nclients_extra / (ssize_t)config.nthreads; nclients_extra_rem_per_thread = (ssize_t)nclients_extra % (ssize_t)config.nthreads; - - std::cout << "nclients_extra: " << nclients_extra << std::endl; - std::cout << "nclients_extra_per_thread: " << nclients_extra_per_thread << std::endl; - std::cout << "nclients_extra_rem_per_thread: " << nclients_extra_rem_per_thread << std::endl; - std::cout << "SECONDS " << config.seconds << std::endl; - std::cout << "NREQS " << config.nreqs << std::endl; - std::cout << "N_TIME " << n_time << std::endl; - std::cout << "C_TIME " << c_time << std::endl; - - std::cout << "nreqs_per_thread" << nreqs_per_thread << std::endl; } std::cout << "starting benchmark..." << std::endl; From 584f5f37343d6566795d60fe14125e45444e6513 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Thu, 23 Jul 2015 10:37:51 -0700 Subject: [PATCH 08/12] Do not allow -r > -t --- src/h2load.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 4ead6d29..856d556f 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -1326,9 +1326,10 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - if (config.rate != 0 && config.nthreads != 1) { - std::cerr << "-r, -t: warning: the -t option will be ignored when the -r " - << "option is in use." << std::endl; + if (config.is_rate_mode() && config.rate < (ssize_t)config.nthreads) { + std::cerr << "-r, -t: the connection rate must be greater than or equal " + << "to the number of threads." << std::endl; + exit(EXIT_FAILURE); } if (!datafile.empty()) { From d6786f75cb1d03c0f46039906c4f8178f705cea4 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Thu, 23 Jul 2015 11:01:09 -0700 Subject: [PATCH 09/12] Getting rid of unused fields in Worker --- src/h2load.cc | 12 +++++++++--- src/h2load.h | 3 --- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 856d556f..7e1d14f6 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -731,11 +731,11 @@ void Client::signal_write() { ev_io_start(worker->loop, &wev); } Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, ssize_t rate, Config *config) : stats(req_todo), loop(ev_loop_new(0)), ssl_ctx(ssl_ctx), config(config), - id(id), tls_info_report_done(false), rate_loop(EV_DEFAULT), current_second(0), nconns_made(0), nclients(nclients), rate(rate) { + id(id), tls_info_report_done(false), current_second(0), nconns_made(0), nclients(nclients), rate(rate) { stats.req_todo = req_todo; progress_interval = std::max((size_t)1, req_todo / 10); - nreqs_per_client = req_todo / nclients; - nreqs_rem = req_todo % nclients; + auto nreqs_per_client = req_todo / nclients; + auto nreqs_rem = req_todo % nclients; if (config->is_rate_mode()) { // create timer that will go off every second @@ -1332,6 +1332,12 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + if (config.is_rate_mode() && config.nconns < (ssize_t)config.nthreads) { + std::cerr << "-C, -t: the total number of connections must be greater than or equal " + << "to the number of threads." << std::endl; + exit(EXIT_FAILURE); + } + if (!datafile.empty()) { config.data_fd = open(datafile.c_str(), O_RDONLY | O_BINARY); if (config.data_fd == -1) { diff --git a/src/h2load.h b/src/h2load.h index 865f2b8f..8e632f8f 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -184,12 +184,9 @@ struct Worker { size_t progress_interval; uint32_t id; bool tls_info_report_done; - struct ev_loop *rate_loop; ssize_t current_second; ssize_t nconns_made; ssize_t nclients; - ssize_t nreqs_per_client; - ssize_t nreqs_rem; ev_timer timeout_watcher; ssize_t rate; From ec617ae6e5dd34d88fb82eec96a3d08990a3c3f9 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Thu, 23 Jul 2015 11:21:12 -0700 Subject: [PATCH 10/12] Getting rid of unused fields in config --- src/h2load.cc | 31 +++++++++++++++++-------------- src/h2load.h | 7 ------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 7e1d14f6..d33ad35d 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -75,7 +75,7 @@ Config::Config() : data_length(-1), addrs(nullptr), nreqs(1), nclients(1), nthreads(1), max_concurrent_streams(-1), window_bits(30), connection_window_bits(30), rate(0), nconns(0), no_tls_proto(PROTO_HTTP2), data_fd(-1), port(0), - default_port(0), verbose(false), current_worker(0) {} + default_port(0), verbose(false) {} Config::~Config() { freeaddrinfo(addrs); @@ -1537,16 +1537,17 @@ int main(int argc, char **argv) { if (!config.is_rate_mode() && config.nclients == 1) { config.nthreads = 1; } + ssize_t seconds = 0; if (config.is_rate_mode()) { // set various config values if ((int)config.nreqs < config.nconns) { - config.seconds = c_time; + seconds = c_time; } else if (config.nconns == 0) { - config.seconds = n_time; + seconds = n_time; } else { - config.seconds = std::min(n_time, c_time); + seconds = std::min(n_time, c_time); } config.nreqs = actual_nreqs; } @@ -1566,7 +1567,7 @@ int main(int argc, char **argv) { // In rate mode, we want each Worker to create a total of // C/t connections. if (config.is_rate_mode()) { - nclients_extra = config.nconns - (config.seconds * config.rate); + nclients_extra = config.nconns - (seconds * config.rate); nclients_extra_per_thread = nclients_extra / (ssize_t)config.nthreads; nclients_extra_rem_per_thread = (ssize_t)nclients_extra % (ssize_t)config.nthreads; } @@ -1575,7 +1576,9 @@ int main(int argc, char **argv) { auto start = std::chrono::steady_clock::now(); - config.workers.reserve(config.nthreads); + std::vector> workers; + + workers.reserve(config.nthreads); #ifndef NOTHREADS std::vector> futures; for (size_t i = 0; i < config.nthreads - 1; ++i) { @@ -1583,15 +1586,15 @@ int main(int argc, char **argv) { auto rate = rate_per_thread + (rate_per_thread_rem-- > 0); auto nclients = nclients_per_thread + (nclients_rem-- > 0); if (config.is_rate_mode()) { - nclients = rate * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + nclients = rate * seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); nreqs = nclients * config.max_concurrent_streams; } std::cout << "spawning thread #" << i << ": " << nclients << " concurrent clients, " << nreqs << " total requests" << std::endl; - config.workers.push_back( + workers.push_back( make_unique(i, ssl_ctx, nreqs, nclients, rate, &config)); - auto &worker = config.workers.back(); + auto &worker = workers.back(); futures.push_back( std::async(std::launch::async, [&worker]() { worker->run(); })); } @@ -1601,15 +1604,15 @@ int main(int argc, char **argv) { auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); auto rate_last = rate_per_thread + (rate_per_thread_rem-- > 0); if (config.is_rate_mode()) { - nclients_last = rate_last * config.seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + nclients_last = rate_last * seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); nreqs_last = nclients_last * config.max_concurrent_streams; } std::cout << "spawning thread #" << (config.nthreads - 1) << ": " << nclients_last << " concurrent clients, " << nreqs_last << " total requests" << std::endl; - config.workers.push_back(make_unique( + workers.push_back(make_unique( config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, rate_last, &config)); - config.workers.back()->run(); + workers.back()->run(); #ifndef NOTHREADS for (auto &fut : futures) { @@ -1622,7 +1625,7 @@ int main(int argc, char **argv) { std::chrono::duration_cast(end - start); Stats stats(0); - for (const auto &w : config.workers) { + for (const auto &w : workers) { const auto &s = w->stats; stats.req_todo += s.req_todo; @@ -1641,7 +1644,7 @@ int main(int argc, char **argv) { } } - auto ts = process_time_stats(config.workers); + auto ts = process_time_stats(workers); // Requests which have not been issued due to connection errors, are // counted towards req_failed and req_error. diff --git a/src/h2load.h b/src/h2load.h index 8e632f8f..f813546d 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -88,13 +88,6 @@ struct Config { uint16_t default_port; bool verbose; - ssize_t current_worker; - std::vector> workers; - SSL_CTX *ssl_ctx; - struct ev_loop *rate_loop; - ssize_t seconds; - ssize_t conns_remainder; - Config(); ~Config(); From 278247faa9a18353e177f7e1a8512510e7b192a8 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Fri, 24 Jul 2015 14:34:53 -0700 Subject: [PATCH 11/12] Starting a second earlier --- src/h2load.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/h2load.cc b/src/h2load.cc index d33ad35d..1e767782 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -771,6 +771,9 @@ void Worker::run() { } } else { ev_timer_again(loop, &timeout_watcher); + + // call callback so that we don't waste the first second + second_timeout_w_cb(loop, &timeout_watcher, 0); } ev_run(loop, 0); } From 12013508bf784ad89e99b3b1626f3cbf4ba61686 Mon Sep 17 00:00:00 2001 From: Nora Shoemaker Date: Fri, 24 Jul 2015 15:35:11 -0700 Subject: [PATCH 12/12] Running clang-format --- src/h2load.cc | 52 ++++++++++++++++++++++++++++++++------------------- src/h2load.h | 4 ++-- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/h2load.cc b/src/h2load.cc index 0e2f10e9..2e7d2b74 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -731,7 +731,8 @@ void Client::signal_write() { ev_io_start(worker->loop, &wev); } Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, ssize_t rate, Config *config) : stats(req_todo), loop(ev_loop_new(0)), ssl_ctx(ssl_ctx), config(config), - id(id), tls_info_report_done(false), current_second(0), nconns_made(0), nclients(nclients), rate(rate) { + id(id), tls_info_report_done(false), current_second(0), nconns_made(0), + nclients(nclients), rate(rate) { stats.req_todo = req_todo; progress_interval = std::max((size_t)1, req_todo / 10); auto nreqs_per_client = req_todo / nclients; @@ -1028,13 +1029,16 @@ void print_help(std::ostream &out) { Options: -n, --requests= Number of requests. - Default: )" << config.nreqs << R"( + Default: )" + << config.nreqs << R"( -c, --clients= Number of concurrent clients. - Default: )" << config.nclients << R"( + Default: )" + << config.nclients << R"( -t, --threads= Number of native threads. - Default: )" << config.nthreads << R"( + Default: )" + << config.nthreads << R"( -i, --input-file= Path of a file with multiple URIs are separated by EOLs. This option will disable URIs getting from command-line. @@ -1051,13 +1055,15 @@ Options: -w, --window-bits= Sets the stream level initial window size to (2**)-1. For SPDY, 2** is used instead. - Default: )" << config.window_bits << R"( + Default: )" + << config.window_bits << R"( -W, --connection-window-bits= Sets the connection level initial window size to (2**)-1. For SPDY, if is strictly less than 16, this option is ignored. Otherwise 2** is used for SPDY. - Default: )" << config.connection_window_bits << R"( + Default: )" + << config.connection_window_bits << R"( -H, --header=
Add/Override a header to the requests. --ciphers= @@ -1075,7 +1081,8 @@ Options: Available protocol: )"; #endif // !HAVE_SPDYLAY out << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( - Default: )" << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( + Default: )" + << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( -d, --data= Post FILE to server. The request method is changed to POST. @@ -1100,7 +1107,8 @@ Options: -v, --verbose Output debug information. --version Display version information and exit. - -h, --help Display this help and exit.)" << std::endl; + -h, --help Display this help and exit.)" + << std::endl; } } // namespace @@ -1333,7 +1341,8 @@ int main(int argc, char **argv) { } if (config.is_rate_mode() && config.nconns < (ssize_t)config.nthreads) { - std::cerr << "-C, -t: the total number of connections must be greater than or equal " + std::cerr << "-C, -t: the total number of connections must be greater than " + "or equal " << "to the number of threads." << std::endl; exit(EXIT_FAILURE); } @@ -1459,11 +1468,12 @@ int main(int argc, char **argv) { config.nreqs, (size_t)(config.max_concurrent_streams * config.nconns)) << " total requests." << std::endl; - actual_nreqs = std::min(config.nreqs, (size_t)(config.max_concurrent_streams * config.nreqs)); + actual_nreqs = std::min( + config.nreqs, (size_t)(config.max_concurrent_streams * config.nreqs)); } } else { - if (config.is_rate_mode() && config.max_concurrent_streams != 0 && - (n_time != c_time) && config.nreqs == 1 && config.nconns != 0) { + if (config.is_rate_mode() && config.max_concurrent_streams != 0 && + (n_time != c_time) && config.nreqs == 1 && config.nconns != 0) { actual_nreqs = config.max_concurrent_streams * config.nconns; } } @@ -1540,7 +1550,7 @@ int main(int argc, char **argv) { if (config.is_rate_mode()) { - // set various config values + // set various config values if ((int)config.nreqs < config.nconns) { seconds = c_time; } else if (config.nconns == 0) { @@ -1564,11 +1574,12 @@ int main(int argc, char **argv) { auto nclients_extra_per_thread = 0; auto nclients_extra_rem_per_thread = 0; // In rate mode, we want each Worker to create a total of - // C/t connections. + // C/t connections. if (config.is_rate_mode()) { nclients_extra = config.nconns - (seconds * config.rate); nclients_extra_per_thread = nclients_extra / (ssize_t)config.nthreads; - nclients_extra_rem_per_thread = (ssize_t)nclients_extra % (ssize_t)config.nthreads; + nclients_extra_rem_per_thread = + (ssize_t)nclients_extra % (ssize_t)config.nthreads; } std::cout << "starting benchmark..." << std::endl; @@ -1585,7 +1596,8 @@ int main(int argc, char **argv) { auto rate = rate_per_thread + (rate_per_thread_rem-- > 0); auto nclients = nclients_per_thread + (nclients_rem-- > 0); if (config.is_rate_mode()) { - nclients = rate * seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + nclients = rate * seconds + nclients_extra_per_thread + + (nclients_extra_rem_per_thread-- > 0); nreqs = nclients * config.max_concurrent_streams; } std::cout << "spawning thread #" << i << ": " << nclients @@ -1603,14 +1615,16 @@ int main(int argc, char **argv) { auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); auto rate_last = rate_per_thread + (rate_per_thread_rem-- > 0); if (config.is_rate_mode()) { - nclients_last = rate_last * seconds + nclients_extra_per_thread + (nclients_extra_rem_per_thread-- > 0); + nclients_last = rate_last * seconds + nclients_extra_per_thread + + (nclients_extra_rem_per_thread-- > 0); nreqs_last = nclients_last * config.max_concurrent_streams; } std::cout << "spawning thread #" << (config.nthreads - 1) << ": " << nclients_last << " concurrent clients, " << nreqs_last << " total requests" << std::endl; - workers.push_back(make_unique( - config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, rate_last, &config)); + workers.push_back(make_unique(config.nthreads - 1, ssl_ctx, + nreqs_last, nclients_last, rate_last, + &config)); workers.back()->run(); #ifndef NOTHREADS diff --git a/src/h2load.h b/src/h2load.h index f813546d..20d323fe 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -183,8 +183,8 @@ struct Worker { ev_timer timeout_watcher; ssize_t rate; - Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, ssize_t rate, - Config *config); + Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, + ssize_t rate, Config *config); ~Worker(); Worker(Worker &&o) = default; void run();