2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2014 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "nghttp2_config.h"
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 # include <sys/socket.h>
33 #endif // HAVE_SYS_SOCKET_H
36 #endif // HAVE_NETDB_H
41 #include <unordered_map>
46 #include <nghttp2/nghttp2.h>
50 #include <openssl/ssl.h>
56 using namespace nghttp2;
60 constexpr auto BACKOFF_WRITE_BUFFER_THRES = 16_k;
66 std::vector<std::vector<nghttp2_nv>> nva;
67 std::vector<std::string> h1reqs;
68 std::vector<ev_tstamp> timings;
69 nghttp2::Headers custom_headers;
72 std::string connect_to_host;
75 // length of upload data
81 // The maximum number of concurrent streams per session.
82 ssize_t max_concurrent_streams;
84 size_t connection_window_bits;
85 // rate at which connections should be made
87 ev_tstamp rate_period;
88 // amount of time for main measurements in timing-based test
90 // amount of time to wait before starting measurements in timing-based test
91 ev_tstamp warm_up_time;
92 // amount of time to wait for activity on a given connection
93 ev_tstamp conn_active_timeout;
94 // amount of time to wait after the last request is made on a connection
95 ev_tstamp conn_inactivity_timeout;
96 enum { PROTO_HTTP2, PROTO_HTTP1_1 } no_tls_proto;
97 uint32_t header_table_size;
98 uint32_t encoder_header_table_size;
99 // file descriptor for upload data
101 // file descriptor to write per-request stats to.
104 uint16_t default_port;
105 uint16_t connect_to_port;
108 std::string base_uri;
109 // true if UNIX domain socket is used. In this case, base_uri is
110 // not used in usual way.
112 // used when UNIX domain socket is used (base_uri_unix is true).
113 sockaddr_un unix_addr;
114 // list of supported NPN/ALPN protocol strings in the order of
116 std::vector<std::string> npn_list;
121 bool is_rate_mode() const;
122 bool is_timing_based_mode() const;
123 bool has_base_uri() const;
127 // time point when request was sent
128 std::chrono::steady_clock::time_point request_time;
129 // same, but in wall clock reference frame
130 std::chrono::system_clock::time_point request_wall_time;
131 // time point when stream was closed
132 std::chrono::steady_clock::time_point stream_close_time;
133 // upload data length sent so far
137 // true if stream was successfully closed. This means stream was
138 // not reset, but it does not mean HTTP level error (e.g., 404).
143 // time client started (i.e., first connect starts)
144 std::chrono::steady_clock::time_point client_start_time;
145 // time client end (i.e., client somehow processed all requests it
146 // is responsible for, and disconnected)
147 std::chrono::steady_clock::time_point client_end_time;
148 // The number of requests completed successful, but not necessarily
149 // means successful HTTP status code.
152 // The following 3 numbers are overwritten each time when connection
155 // time connect starts
156 std::chrono::steady_clock::time_point connect_start_time;
158 std::chrono::steady_clock::time_point connect_time;
159 // time to first byte (TTFB)
160 std::chrono::steady_clock::time_point ttfb;
164 // min, max, mean and sd (standard deviation)
165 double min, max, mean, sd;
166 // percentage of samples inside mean -/+ sd
175 // time to first byte (TTFB)
177 // request per second for each client
182 Stats(size_t req_todo, size_t nclients);
183 // The total number of requests
185 // The number of requests issued so far
187 // The number of requests finished
189 // The number of requests completed successful, but not necessarily
190 // means successful HTTP status code.
192 // The number of requests marked as success. HTTP status code is
193 // also considered as success. This is subset of req_done.
194 size_t req_status_success;
195 // The number of requests failed. This is subset of req_done.
197 // The number of requests failed due to network errors. This is
198 // subset of req_failed.
200 // The number of requests that failed due to timeout.
202 // The number of bytes received on the "wire". If SSL/TLS is used,
203 // this is the number of decrypted bytes the application received.
205 // The number of bytes received for header fields. This is
206 // compressed version.
208 // The number of bytes received for header fields after they are
210 int64_t bytes_head_decomp;
211 // The number of bytes received in DATA frame.
213 // The number of each HTTP status category, status[i] is status code
214 // in the range [i*100, (i+1)*100).
215 std::array<size_t, 6> status;
216 // The statistics per request
217 std::vector<RequestStat> req_stats;
218 // THe statistics per client
219 std::vector<ClientStat> client_stats;
222 enum ClientState { CLIENT_IDLE, CLIENT_CONNECTED };
224 // This type tells whether the client is in warmup phase or not or is over
226 INITIAL_IDLE, // Initial idle state before warm-up phase
227 WARM_UP, // Warm up phase when no measurements are done
228 MAIN_DURATION, // Main measurement phase; if timing-based
229 // test is not run, this is the default phase
230 DURATION_OVER // This phase occurs after the measurements are over
235 // We use reservoir sampling method
237 // maximum number of samples
239 // number of samples seen, including discarded samples.
246 Sampling request_times_smp;
248 struct ev_loop *loop;
251 size_t progress_interval;
253 bool tls_info_report_done;
254 bool app_info_report_done;
256 // number of clients this worker handles
258 // number of requests each client issues
259 size_t nreqs_per_client;
260 // at most nreqs_rem clients get an extra request
263 // maximum number of samples in this worker thread
265 ev_timer timeout_watcher;
266 // The next client ID this worker assigns
267 uint32_t next_client_id;
268 // Keeps track of the current phase (for timing-based experiment) for the
271 // We need to keep track of the clients in order to stop them when needed
272 std::vector<Client *> clients;
273 // This is only active when there is not a bounded number of requests
275 ev_timer duration_watcher;
276 ev_timer warmup_watcher;
278 Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients,
279 size_t rate, size_t max_samples, Config *config);
281 Worker(Worker &&o) = default;
283 void sample_req_stat(RequestStat *req_stat);
284 void sample_client_stat(ClientStat *cstat);
285 void report_progress();
286 void report_rate_progress();
287 // This function calls the destructors of all the clients.
288 void stop_all_clients();
289 // This function frees a client from the list of clients for this Worker.
290 void free_client(Client *);
294 RequestStat req_stat;
301 std::unordered_map<int32_t, Stream> streams;
303 std::unique_ptr<Session> session;
306 std::function<int(Client &)> readfn, writefn;
309 ev_timer request_timeout_watcher;
311 // Address for the current address. When try_new_connection() is
312 // used and current_addr is not nullptr, it is used instead of
313 // trying next address though next_addr. To try new address, set
314 // nullptr to current_addr before calling connect().
315 addrinfo *current_addr;
318 // The number of requests this client has to issue.
320 // The number of requests left to issue
322 // The number of requests currently have started, but not abandoned
325 // The number of requests this client has issued so far.
327 // The number of requests this client has done so far.
329 // The client id per worker
332 ev_timer conn_active_watcher;
333 ev_timer conn_inactivity_watcher;
334 std::string selected_proto;
335 bool new_connection_requested;
336 // true if the current connection will be closed, and no more new
337 // request cannot be processed.
340 enum { ERR_CONNECT_FAIL = -100 };
342 Client(uint32_t id, Worker *worker, size_t req_todo);
344 int make_socket(addrinfo *addr);
348 // Call this function when do_read() returns -1. This function
349 // tries to connect to the remote host again if it is requested. If
350 // so, this function returns 0, and this object should be retained.
351 // Otherwise, this function returns -1, and this object should be
353 int try_again_or_fail();
355 void restart_timeout();
356 int submit_request();
357 void process_request_failure();
358 void process_timedout_streams();
359 void process_abandoned_streams();
360 void report_tls_info();
361 void report_app_info();
362 void terminate_session();
363 // Asks client to create new connection, instead of just fail.
364 void try_new_connection();
369 // low-level I/O callback functions called by do_read/do_write
377 int on_read(const uint8_t *data, size_t len);
380 int connection_made();
382 void on_request(int32_t stream_id);
383 void on_header(int32_t stream_id, const uint8_t *name, size_t namelen,
384 const uint8_t *value, size_t valuelen);
385 void on_status_code(int32_t stream_id, uint16_t status);
386 // |success| == true means that the request/response was exchanged
387 // |successfully, but it does not mean response carried successful
388 // |HTTP status code.
389 void on_stream_close(int32_t stream_id, bool success, bool final = false);
390 // Returns RequestStat for |stream_id|. This function must be
391 // called after on_request(stream_id), and before
392 // on_stream_close(stream_id, ...). Otherwise, this will return
394 RequestStat *get_req_stat(int32_t stream_id);
396 void record_request_time(RequestStat *req_stat);
397 void record_connect_start_time();
398 void record_connect_time();
400 void clear_connect_times();
401 void record_client_start_time();
402 void record_client_end_time();
407 } // namespace h2load