h2load: Perform Sampling for client as well
This commit is contained in:
parent
9cbb8174bb
commit
a52920cec0
|
@ -105,8 +105,9 @@ Stats::Stats(size_t req_todo, size_t nclients)
|
||||||
: req_todo(0), req_started(0), req_done(0), req_success(0),
|
: req_todo(0), req_started(0), req_done(0), req_success(0),
|
||||||
req_status_success(0), req_failed(0), req_error(0), req_timedout(0),
|
req_status_success(0), req_failed(0), req_error(0), req_timedout(0),
|
||||||
bytes_total(0), bytes_head(0), bytes_head_decomp(0), bytes_body(0),
|
bytes_total(0), bytes_head(0), bytes_head_decomp(0), bytes_body(0),
|
||||||
status(), client_stats(nclients) {
|
status() {
|
||||||
req_stats.reserve(std::min(req_todo, MAX_STATS));
|
req_stats.reserve(std::min(req_todo, MAX_STATS));
|
||||||
|
client_stats.reserve(std::min(nclients, MAX_STATS));
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream::Stream() : status_success(-1) {}
|
Stream::Stream() : status_success(-1) {}
|
||||||
|
@ -288,7 +289,7 @@ void client_request_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Client::Client(uint32_t id, Worker *worker, size_t req_todo)
|
Client::Client(uint32_t id, Worker *worker, size_t req_todo)
|
||||||
: worker(worker), ssl(nullptr), next_addr(config.addrs),
|
: cstat{}, worker(worker), ssl(nullptr), next_addr(config.addrs),
|
||||||
current_addr(nullptr), reqidx(0), state(CLIENT_IDLE), req_todo(req_todo),
|
current_addr(nullptr), reqidx(0), state(CLIENT_IDLE), req_todo(req_todo),
|
||||||
req_started(0), req_done(0), id(id), fd(-1),
|
req_started(0), req_done(0), id(id), fd(-1),
|
||||||
new_connection_requested(false) {
|
new_connection_requested(false) {
|
||||||
|
@ -316,6 +317,12 @@ Client::~Client() {
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sampling_should_pick(worker->client_smp)) {
|
||||||
|
sampling_advance_point(worker->client_smp);
|
||||||
|
worker->sample_client_stat(&cstat);
|
||||||
|
}
|
||||||
|
++worker->client_smp.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Client::do_read() { return readfn(*this); }
|
int Client::do_read() { return readfn(*this); }
|
||||||
|
@ -655,7 +662,6 @@ void Client::on_stream_close(int32_t stream_id, bool success, bool final) {
|
||||||
if (success) {
|
if (success) {
|
||||||
req_stat->completed = true;
|
req_stat->completed = true;
|
||||||
++worker->stats.req_success;
|
++worker->stats.req_success;
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
++cstat.req_success;
|
++cstat.req_success;
|
||||||
|
|
||||||
if (streams[stream_id].status_success == 1) {
|
if (streams[stream_id].status_success == 1) {
|
||||||
|
@ -1044,17 +1050,14 @@ void Client::record_request_time(RequestStat *req_stat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::record_connect_start_time() {
|
void Client::record_connect_start_time() {
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
cstat.connect_start_time = std::chrono::steady_clock::now();
|
cstat.connect_start_time = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::record_connect_time() {
|
void Client::record_connect_time() {
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
cstat.connect_time = std::chrono::steady_clock::now();
|
cstat.connect_time = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::record_ttfb() {
|
void Client::record_ttfb() {
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
if (recorded(cstat.ttfb)) {
|
if (recorded(cstat.ttfb)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1063,16 +1066,12 @@ void Client::record_ttfb() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::clear_connect_times() {
|
void Client::clear_connect_times() {
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
|
|
||||||
cstat.connect_start_time = std::chrono::steady_clock::time_point();
|
cstat.connect_start_time = std::chrono::steady_clock::time_point();
|
||||||
cstat.connect_time = std::chrono::steady_clock::time_point();
|
cstat.connect_time = std::chrono::steady_clock::time_point();
|
||||||
cstat.ttfb = std::chrono::steady_clock::time_point();
|
cstat.ttfb = std::chrono::steady_clock::time_point();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::record_client_start_time() {
|
void Client::record_client_start_time() {
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
|
|
||||||
// Record start time only once at the very first connection is going
|
// Record start time only once at the very first connection is going
|
||||||
// to be made.
|
// to be made.
|
||||||
if (recorded(cstat.client_start_time)) {
|
if (recorded(cstat.client_start_time)) {
|
||||||
|
@ -1083,8 +1082,6 @@ void Client::record_client_start_time() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::record_client_end_time() {
|
void Client::record_client_end_time() {
|
||||||
auto &cstat = worker->stats.client_stats[id];
|
|
||||||
|
|
||||||
// Unlike client_start_time, we overwrite client_end_time. This
|
// Unlike client_start_time, we overwrite client_end_time. This
|
||||||
// handles multiple connect/disconnect for HTTP/1.1 benchmark.
|
// handles multiple connect/disconnect for HTTP/1.1 benchmark.
|
||||||
cstat.client_end_time = std::chrono::steady_clock::now();
|
cstat.client_end_time = std::chrono::steady_clock::now();
|
||||||
|
@ -1114,6 +1111,7 @@ Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients,
|
||||||
timeout_watcher.data = this;
|
timeout_watcher.data = this;
|
||||||
|
|
||||||
sampling_init(request_times_smp, req_todo, MAX_STATS);
|
sampling_init(request_times_smp, req_todo, MAX_STATS);
|
||||||
|
sampling_init(client_smp, nclients, MAX_STATS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Worker::~Worker() {
|
Worker::~Worker() {
|
||||||
|
@ -1151,6 +1149,11 @@ void Worker::sample_req_stat(RequestStat *req_stat) {
|
||||||
assert(stats.req_stats.size() <= MAX_STATS);
|
assert(stats.req_stats.size() <= MAX_STATS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worker::sample_client_stat(ClientStat *cstat) {
|
||||||
|
stats.client_stats.push_back(*cstat);
|
||||||
|
assert(stats.client_stats.size() <= MAX_STATS);
|
||||||
|
}
|
||||||
|
|
||||||
void Worker::report_progress() {
|
void Worker::report_progress() {
|
||||||
if (id != 0 || config->is_rate_mode() || stats.req_done % progress_interval) {
|
if (id != 0 || config->is_rate_mode() || stats.req_done % progress_interval) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -222,6 +222,7 @@ struct Sampling {
|
||||||
struct Worker {
|
struct Worker {
|
||||||
Stats stats;
|
Stats stats;
|
||||||
Sampling request_times_smp;
|
Sampling request_times_smp;
|
||||||
|
Sampling client_smp;
|
||||||
struct ev_loop *loop;
|
struct ev_loop *loop;
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
Config *config;
|
Config *config;
|
||||||
|
@ -247,6 +248,7 @@ struct Worker {
|
||||||
Worker(Worker &&o) = default;
|
Worker(Worker &&o) = default;
|
||||||
void run();
|
void run();
|
||||||
void sample_req_stat(RequestStat *req_stat);
|
void sample_req_stat(RequestStat *req_stat);
|
||||||
|
void sample_client_stat(ClientStat *cstat);
|
||||||
void report_progress();
|
void report_progress();
|
||||||
void report_rate_progress();
|
void report_rate_progress();
|
||||||
};
|
};
|
||||||
|
@ -259,6 +261,7 @@ struct Stream {
|
||||||
|
|
||||||
struct Client {
|
struct Client {
|
||||||
std::unordered_map<int32_t, Stream> streams;
|
std::unordered_map<int32_t, Stream> streams;
|
||||||
|
ClientStat cstat;
|
||||||
std::unique_ptr<Session> session;
|
std::unique_ptr<Session> session;
|
||||||
ev_io wev;
|
ev_io wev;
|
||||||
ev_io rev;
|
ev_io rev;
|
||||||
|
|
Loading…
Reference in New Issue