Commit a52920ce authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

h2load: Perform Sampling for client as well

parent 9cbb8174
...@@ -105,8 +105,9 @@ Stats::Stats(size_t req_todo, size_t nclients) ...@@ -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) { ...@@ -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() { ...@@ -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) { ...@@ -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) { ...@@ -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() { ...@@ -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() { ...@@ -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, ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment