h2load: Explicitly count the number of requests left and inflight

This commit is contained in:
Tatsuhiro Tsujikawa 2017-01-26 00:16:12 +09:00
parent 712b08e8ed
commit 7e6eb7e02a
3 changed files with 34 additions and 37 deletions

View File

@ -269,9 +269,7 @@ void conn_timeout_cb(EV_P_ ev_timer *w, int revents) {
namespace { namespace {
bool check_stop_client_request_timeout(Client *client, ev_timer *w) { bool check_stop_client_request_timeout(Client *client, ev_timer *w) {
auto nreq = client->req_todo - client->req_started; if (client->req_left == 0 ||
if (nreq == 0 ||
client->streams.size() >= client->session->max_concurrent_streams()) { client->streams.size() >= client->session->max_concurrent_streams()) {
// no more requests to make, stop timer // no more requests to make, stop timer
ev_timer_stop(client->worker->loop, w); ev_timer_stop(client->worker->loop, w);
@ -330,6 +328,8 @@ Client::Client(uint32_t id, Worker *worker, size_t req_todo)
reqidx(0), reqidx(0),
state(CLIENT_IDLE), state(CLIENT_IDLE),
req_todo(req_todo), req_todo(req_todo),
req_left(req_todo),
req_inflight(0),
req_started(0), req_started(0),
req_done(0), req_done(0),
id(id), id(id),
@ -467,16 +467,13 @@ int Client::try_again_or_fail() {
if (new_connection_requested) { if (new_connection_requested) {
new_connection_requested = false; new_connection_requested = false;
if (req_started < req_todo) { if (req_left) {
// At the moment, we don't have a facility to re-start request // At the moment, we don't have a facility to re-start request
// already in in-flight. Make them fail. // already in in-flight. Make them fail.
auto req_abandoned = req_started - req_done; worker->stats.req_failed += req_inflight;
worker->stats.req_error += req_inflight;
worker->stats.req_failed += req_abandoned; req_inflight = 0;
worker->stats.req_error += req_abandoned;
worker->stats.req_done += req_abandoned;
req_done = req_started;
// Keep using current address // Keep using current address
if (connect() == 0) { if (connect() == 0) {
@ -528,16 +525,18 @@ void Client::disconnect() {
} }
int Client::submit_request() { int Client::submit_request() {
++worker->stats.req_started;
if (session->submit_request() != 0) { if (session->submit_request() != 0) {
return -1; return -1;
} }
++worker->stats.req_started;
--req_left;
++req_started; ++req_started;
++req_inflight;
// if an active timeout is set and this is the last request to be submitted // if an active timeout is set and this is the last request to be submitted
// on this connection, start the active timeout. // on this connection, start the active timeout.
if (worker->config->conn_active_timeout > 0. && req_started >= req_todo) { if (worker->config->conn_active_timeout > 0. && req_left == 0) {
ev_timer_start(worker->loop, &conn_active_watcher); ev_timer_start(worker->loop, &conn_active_watcher);
} }
@ -551,34 +550,29 @@ void Client::process_timedout_streams() {
} }
} }
auto req_timed_out = req_todo - req_done; worker->stats.req_timedout += req_inflight;
worker->stats.req_timedout += req_timed_out;
process_abandoned_streams(); process_abandoned_streams();
} }
void Client::process_abandoned_streams() { void Client::process_abandoned_streams() {
auto req_abandoned = req_todo - req_done; auto req_abandoned = req_inflight + req_left;
worker->stats.req_failed += req_abandoned; worker->stats.req_failed += req_abandoned;
worker->stats.req_error += req_abandoned; worker->stats.req_error += req_abandoned;
worker->stats.req_done += req_abandoned;
req_done = req_todo; req_inflight = 0;
req_left = 0;
} }
void Client::process_request_failure() { void Client::process_request_failure() {
auto req_abandoned = req_todo - req_started; worker->stats.req_failed += req_left;
worker->stats.req_error += req_left;
worker->stats.req_failed += req_abandoned; req_left = 0;
worker->stats.req_error += req_abandoned;
worker->stats.req_done += req_abandoned;
req_done += req_abandoned; if (req_inflight == 0) {
if (req_done == req_todo) {
terminate_session(); terminate_session();
return;
} }
} }
@ -711,6 +705,9 @@ void Client::on_status_code(int32_t stream_id, uint16_t status) {
} }
void Client::on_stream_close(int32_t stream_id, bool success, bool final) { void Client::on_stream_close(int32_t stream_id, bool success, bool final) {
++req_done;
--req_inflight;
auto req_stat = get_req_stat(stream_id); auto req_stat = get_req_stat(stream_id);
if (!req_stat) { if (!req_stat) {
return; return;
@ -741,23 +738,19 @@ void Client::on_stream_close(int32_t stream_id, bool success, bool final) {
} }
++worker->stats.req_done; ++worker->stats.req_done;
++req_done;
worker->report_progress(); worker->report_progress();
streams.erase(stream_id); streams.erase(stream_id);
if (req_done == req_todo) { if (req_left == 0 && req_inflight == 0) {
terminate_session(); terminate_session();
return; return;
} }
if (!config.timing_script && !final) { if (!config.timing_script && !final && req_left > 0 &&
if (req_started < req_todo) { submit_request() != 0) {
if (submit_request() != 0) {
process_request_failure(); process_request_failure();
}
return; return;
} }
}
} }
RequestStat *Client::get_req_stat(int32_t stream_id) { RequestStat *Client::get_req_stat(int32_t stream_id) {
@ -871,8 +864,7 @@ int Client::connection_made() {
record_connect_time(); record_connect_time();
if (!config.timing_script) { if (!config.timing_script) {
auto nreq = auto nreq = std::min(req_left, session->max_concurrent_streams());
std::min(req_todo - req_started, session->max_concurrent_streams());
for (; nreq > 0; --nreq) { for (; nreq > 0; --nreq) {
if (submit_request() != 0) { if (submit_request() != 0) {
process_request_failure(); process_request_failure();

View File

@ -292,6 +292,11 @@ struct Client {
ClientState state; ClientState state;
// The number of requests this client has to issue. // The number of requests this client has to issue.
size_t req_todo; size_t req_todo;
// The number of requests left to issue
size_t req_left;
// The number of requests currently have started, but not abandoned
// or finished.
size_t req_inflight;
// The number of requests this client has issued so far. // The number of requests this client has issued so far.
size_t req_started; size_t req_started;
// The number of requests this client has done so far. // The number of requests this client has done so far.

View File

@ -100,7 +100,7 @@ int htp_msg_completecb(http_parser *htp) {
http_parser_pause(htp, 1); http_parser_pause(htp, 1);
// Connection is going down. If we have still request to do, // Connection is going down. If we have still request to do,
// create new connection and keep on doing the job. // create new connection and keep on doing the job.
if (client->req_started < client->req_todo) { if (client->req_left) {
client->try_new_connection(); client->try_new_connection();
} }