h2load: Explicitly count the number of requests left and inflight
This commit is contained in:
parent
712b08e8ed
commit
7e6eb7e02a
|
@ -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,24 +738,20 @@ 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) {
|
||||||
auto it = streams.find(stream_id);
|
auto it = streams.find(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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue