@@ -77,157 +77,256 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
77
77
#[ derive( Parser , Debug , Clone ) ]
78
78
#[ clap( name = "client" ) ]
79
79
pub struct ClientOpt {
80
- /// Request URLs. The host of the first one is used as SNI in Client Hello.
80
+ /// Server's address.
81
+ #[ clap( short, long, value_name = "ADDR" ) ]
82
+ pub connect_to : Option < SocketAddr > ,
83
+
84
+ /// Optional local IP addresses for client. e.g 192.168.1.10,192.168.2.20
85
+ #[ clap( long, value_delimiter = ',' , value_name = "ADDR" ) ]
86
+ pub local_addresses : Vec < IpAddr > ,
87
+
88
+ /// Request URLs. The host of the first url is used as TLS SNI.
81
89
#[ clap( value_delimiter = ' ' ) ]
82
90
pub urls : Vec < Url > ,
83
91
84
92
/// Number of threads.
85
- #[ clap( short, long, default_value = "1" , value_name = "NUM" ) ]
93
+ #[ clap(
94
+ short,
95
+ long,
96
+ default_value = "1" ,
97
+ value_name = "NUM" ,
98
+ help_heading = "Concurrency"
99
+ ) ]
86
100
pub threads : u32 ,
87
101
88
102
/// Number of concurrent connections per thread.
89
- #[ clap( long, default_value = "1" , value_name = "NUM" ) ]
103
+ #[ clap(
104
+ long,
105
+ default_value = "1" ,
106
+ value_name = "NUM" ,
107
+ help_heading = "Concurrency"
108
+ ) ]
90
109
pub max_concurrent_conns : u32 ,
91
110
92
- /// Number of requests per thread. "0" means infinity mode.
93
- #[ clap( long, default_value = "1" , value_name = "NUM" ) ]
94
- pub max_requests_per_thread : u64 ,
111
+ /// Number of concurrent requests per connection.
112
+ #[ clap(
113
+ long,
114
+ default_value = "1" ,
115
+ value_name = "NUM" ,
116
+ help_heading = "Concurrency"
117
+ ) ]
118
+ pub max_concurrent_requests : u64 ,
95
119
96
- /// Number of max requests per connection. "0" means infinity mode.
97
- #[ clap( long, default_value = "1" , value_name = "NUM" ) ]
120
+ /// Number of max requests per connection before re-establishment. "0" means infinity mode.
121
+ #[ clap(
122
+ long,
123
+ default_value = "1" ,
124
+ value_name = "NUM" ,
125
+ help_heading = "Concurrency"
126
+ ) ]
98
127
pub max_requests_per_conn : u64 ,
99
128
100
- /// Number of max concurrent requests per connection.
101
- #[ clap( long, default_value = "1" , value_name = "NUM" ) ]
102
- pub max_concurrent_requests : u64 ,
129
+ /// Total number of requests to send per thread. "0" means infinity mode.
130
+ /// Values below number of urls will be considered as number of urls.
131
+ #[ clap(
132
+ long,
133
+ default_value = "1" ,
134
+ value_name = "NUM" ,
135
+ help_heading = "Concurrency"
136
+ ) ]
137
+ pub total_requests_per_thread : u64 ,
103
138
104
139
/// Benchmarking duration in seconds. "0" means infinity mode.
105
- /// Client will exit if either the max_requests or duration is reached.
106
- #[ clap( short, long, default_value = "0" , value_name = "TIME" ) ]
140
+ /// Client will exit upon reaching the total_requests_per_thread or duration limit.
141
+ #[ clap(
142
+ short,
143
+ long,
144
+ default_value = "0" ,
145
+ value_name = "TIME" ,
146
+ help_heading = "Concurrency"
147
+ ) ]
107
148
pub duration : u64 ,
108
149
109
- /// Client will exit if consecutive failure reaches the threshold at the beginning.
110
- #[ clap( long, default_value = "10" , value_name = "NUM" ) ]
111
- pub connection_failure_threshold : u64 ,
112
-
113
- /// Number of max samples per thread used for request time statistics.
114
- #[ clap( long, default_value = "100000" , value_name = "NUM" ) ]
115
- pub max_sample : usize ,
116
-
117
- /// Print response header and body to stdout.
118
- #[ clap( short, long) ]
119
- pub print_res : bool ,
120
-
121
- /// Log level, support OFF/ERROR/WARN/INFO/DEBUG/TRACE.
122
- #[ clap( long, default_value = "INFO" , value_name = "STR" ) ]
123
- pub log_level : log:: LevelFilter ,
124
-
125
- /// Log file path. If no file is specified, logs will be written to `stderr`.
126
- #[ clap( long, value_name = "FILE" ) ]
127
- pub log_file : Option < String > ,
128
-
129
- /// Override server's address.
130
- #[ clap( short, long, value_name = "ADDR" ) ]
131
- pub connect_to : Option < SocketAddr > ,
132
-
133
150
/// ALPN, separated by ",".
134
151
#[ clap(
135
152
short,
136
153
long,
137
154
value_delimiter = ',' ,
138
155
default_value = "h3,http/0.9,hq-interop" ,
139
- value_name = "STR"
156
+ value_name = "STR" ,
157
+ help_heading = "Protocol"
140
158
) ]
141
159
pub alpn : Vec < ApplicationProto > ,
142
160
143
- /// Dump response body into the given directory.
144
- /// If the specified directory does not exist, a new directory will be created.
145
- #[ clap( long, value_name = "DIR" ) ]
146
- pub dump_dir : Option < String > ,
147
-
148
161
/// File used for session resumption.
149
- #[ clap( short, long, value_name = "FILE" ) ]
162
+ #[ clap( short, long, value_name = "FILE" , help_heading = "Protocol" ) ]
150
163
pub session_file : Option < String > ,
151
164
152
165
/// Enable early data.
153
- #[ clap( short, long) ]
166
+ #[ clap( short, long, help_heading = "Protocol" ) ]
154
167
pub enable_early_data : bool ,
155
168
156
169
/// Disable stateless reset.
157
- #[ clap( long) ]
170
+ #[ clap( long, help_heading = "Protocol" ) ]
158
171
pub disable_stateless_reset : bool ,
159
172
160
173
/// Congestion control algorithm.
161
- #[ clap( long, default_value = "BBR" ) ]
174
+ #[ clap( long, default_value = "BBR" , help_heading = "Protocol" ) ]
162
175
pub congestion_control_algor : CongestionControlAlgorithm ,
163
176
164
177
/// Initial congestion window in packets.
165
- #[ clap( long, default_value = "32" , value_name = "NUM" ) ]
178
+ #[ clap(
179
+ long,
180
+ default_value = "32" ,
181
+ value_name = "NUM" ,
182
+ help_heading = "Protocol"
183
+ ) ]
166
184
pub initial_congestion_window : u64 ,
167
185
168
186
/// Minimum congestion window in packets.
169
- #[ clap( long, default_value = "4" , value_name = "NUM" ) ]
187
+ #[ clap(
188
+ long,
189
+ default_value = "4" ,
190
+ value_name = "NUM" ,
191
+ help_heading = "Protocol"
192
+ ) ]
170
193
pub min_congestion_window : u64 ,
171
194
172
195
/// Enable multipath transport.
173
- #[ clap( long) ]
196
+ #[ clap( long, help_heading = "Protocol" ) ]
174
197
pub enable_multipath : bool ,
175
198
176
199
/// Multipath scheduling algorithm.
177
- #[ clap( long, default_value = "MINRTT" ) ]
200
+ #[ clap( long, default_value = "MINRTT" , help_heading = "Protocol" ) ]
178
201
pub multipath_algor : MultipathAlgorithm ,
179
202
180
- /// Optional local IP addresses for client. e.g 192.168.1.10,192.168.2.20
181
- #[ clap( long, value_delimiter = ',' , value_name = "ADDR" ) ]
182
- pub local_addresses : Vec < IpAddr > ,
183
-
184
203
/// Set active_connection_id_limit transport parameter. Values lower than 2 will be ignored.
185
- #[ clap( long, default_value = "2" , value_name = "NUM" ) ]
204
+ #[ clap(
205
+ long,
206
+ default_value = "2" ,
207
+ value_name = "NUM" ,
208
+ help_heading = "Protocol"
209
+ ) ]
186
210
pub active_cid_limit : u64 ,
187
211
188
212
/// Set max_udp_payload_size transport parameter.
189
- #[ clap( long, default_value = "65527" , value_name = "NUM" ) ]
213
+ #[ clap(
214
+ long,
215
+ default_value = "65527" ,
216
+ value_name = "NUM" ,
217
+ help_heading = "Protocol"
218
+ ) ]
190
219
pub recv_udp_payload_size : u16 ,
191
220
192
221
/// Set the maximum outgoing UDP payload size.
193
- #[ clap( long, default_value = "1200" , value_name = "NUM" ) ]
222
+ #[ clap(
223
+ long,
224
+ default_value = "1200" ,
225
+ value_name = "NUM" ,
226
+ help_heading = "Protocol"
227
+ ) ]
194
228
pub send_udp_payload_size : usize ,
195
229
196
230
/// Handshake timeout in microseconds.
197
- #[ clap( long, default_value = "10000" , value_name = "TIME" ) ]
231
+ #[ clap(
232
+ long,
233
+ default_value = "10000" ,
234
+ value_name = "TIME" ,
235
+ help_heading = "Protocol"
236
+ ) ]
198
237
pub handshake_timeout : u64 ,
199
238
200
239
/// Connection idle timeout in microseconds.
201
- #[ clap( long, default_value = "30000" , value_name = "TIME" ) ]
240
+ #[ clap(
241
+ long,
242
+ default_value = "30000" ,
243
+ value_name = "TIME" ,
244
+ help_heading = "Protocol"
245
+ ) ]
202
246
pub idle_timeout : u64 ,
203
247
204
248
/// Initial RTT in milliseconds.
205
- #[ clap( long, default_value = "333" , value_name = "TIME" ) ]
249
+ #[ clap(
250
+ long,
251
+ default_value = "333" ,
252
+ value_name = "TIME" ,
253
+ help_heading = "Protocol"
254
+ ) ]
206
255
pub initial_rtt : u64 ,
207
256
208
257
/// Linear factor for calculating the probe timeout.
209
- #[ clap( long, default_value = "10" , value_name = "NUM" ) ]
258
+ #[ clap(
259
+ long,
260
+ default_value = "10" ,
261
+ value_name = "NUM" ,
262
+ help_heading = "Protocol"
263
+ ) ]
210
264
pub pto_linear_factor : u64 ,
211
265
212
266
/// Upper limit of probe timeout in microseconds.
213
- #[ clap( long, default_value = "10000" , value_name = "TIME" ) ]
267
+ #[ clap(
268
+ long,
269
+ default_value = "10000" ,
270
+ value_name = "TIME" ,
271
+ help_heading = "Protocol"
272
+ ) ]
214
273
pub max_pto : u64 ,
215
274
275
+ /// Length of connection id in bytes.
276
+ #[ clap(
277
+ long,
278
+ default_value = "8" ,
279
+ value_name = "NUM" ,
280
+ help_heading = "Protocol"
281
+ ) ]
282
+ pub cid_len : usize ,
283
+
284
+ /// Print response header and body to stdout.
285
+ #[ clap( short, long, help_heading = "Output" ) ]
286
+ pub print_res : bool ,
287
+
288
+ /// Dump response body into the given directory.
289
+ /// If the specified directory does not exist, a new directory will be created.
290
+ #[ clap( long, value_name = "DIR" , help_heading = "Output" ) ]
291
+ pub dump_dir : Option < String > ,
292
+
293
+ /// Log level, support OFF/ERROR/WARN/INFO/DEBUG/TRACE.
294
+ #[ clap(
295
+ long,
296
+ default_value = "INFO" ,
297
+ value_name = "STR" ,
298
+ help_heading = "Output"
299
+ ) ]
300
+ pub log_level : log:: LevelFilter ,
301
+
302
+ /// Log file path. If no file is specified, logs will be written to `stderr`.
303
+ #[ clap( long, value_name = "FILE" , help_heading = "Output" ) ]
304
+ pub log_file : Option < String > ,
305
+
216
306
/// Save TLS key log into the given file.
217
- #[ clap( short, long, value_name = "FILE" ) ]
307
+ #[ clap( short, long, value_name = "FILE" , help_heading = "Output" ) ]
218
308
pub keylog_file : Option < String > ,
219
309
220
310
/// Save qlog file (<trace_id>.qlog) into the given directory.
221
- #[ clap( long, value_name = "DIR" ) ]
311
+ #[ clap( long, value_name = "DIR" , help_heading = "Output" ) ]
222
312
pub qlog_dir : Option < String > ,
223
313
224
- /// Length of connection id in bytes .
225
- #[ clap( long, default_value = "8 " , value_name = "NUM" ) ]
226
- pub cid_len : usize ,
314
+ /// Client will exit if consecutive failure reaches the threshold at the beginning .
315
+ #[ clap( long, default_value = "10 " , value_name = "NUM" , help_heading = "Misc ") ]
316
+ pub connection_failure_threshold : u64 ,
227
317
228
318
/// Batch size for sending packets.
229
- #[ clap( long, default_value = "1" , value_name = "NUM" ) ]
319
+ #[ clap( long, default_value = "1" , value_name = "NUM" , help_heading = "Misc" ) ]
230
320
pub send_batch_size : usize ,
321
+
322
+ /// Number of max samples per thread used for request time statistics.
323
+ #[ clap(
324
+ long,
325
+ default_value = "100000" ,
326
+ value_name = "NUM" ,
327
+ help_heading = "Misc"
328
+ ) ]
329
+ pub max_sample : usize ,
231
330
}
232
331
233
332
const MAX_BUF_SIZE : usize = 65536 ;
@@ -559,8 +658,8 @@ impl Worker {
559
658
560
659
if ( self . option . duration > 0
561
660
&& ( Instant :: now ( ) - self . start_time ) . as_secs ( ) > self . option . duration )
562
- || ( self . option . max_requests_per_thread > 0
563
- && worker_ctx. request_done >= self . option . max_requests_per_thread )
661
+ || ( self . option . total_requests_per_thread > 0
662
+ && worker_ctx. request_done >= self . option . total_requests_per_thread )
564
663
{
565
664
debug ! (
566
665
"worker should exit, concurrent conns {}, request sent {}, request done {}" ,
@@ -1427,9 +1526,9 @@ fn parse_option() -> std::result::Result<ClientOpt, clap::error::Error> {
1427
1526
option. max_requests_per_conn = max ( option. max_requests_per_conn , option. urls . len ( ) as u64 ) ;
1428
1527
}
1429
1528
1430
- if option. max_requests_per_thread != 0 {
1431
- option. max_requests_per_thread =
1432
- max ( option. max_requests_per_thread , option. urls . len ( ) as u64 ) ;
1529
+ if option. total_requests_per_thread != 0 {
1530
+ option. total_requests_per_thread =
1531
+ max ( option. total_requests_per_thread , option. urls . len ( ) as u64 ) ;
1433
1532
}
1434
1533
1435
1534
Ok ( option)
0 commit comments