loadtest 7.1.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/FUNDING.yml +13 -0
- package/README.md +71 -49
- package/bin/loadtest.js +3 -2
- package/bin/tcp-performance.js +21 -0
- package/bin/testserver.js +28 -26
- package/doc/api.md +103 -52
- package/doc/tcp-sockets.md +569 -0
- package/lib/baseClient.js +3 -7
- package/lib/cluster.js +1 -1
- package/lib/httpClient.js +18 -43
- package/lib/latency.js +27 -27
- package/lib/loadtest.js +26 -69
- package/lib/options.js +5 -1
- package/lib/parser.js +167 -0
- package/lib/pool.js +106 -0
- package/lib/result.js +22 -14
- package/lib/tcpClient.js +198 -0
- package/lib/testserver.js +24 -7
- package/lib/websocket.js +5 -11
- package/package.json +3 -2
- package/test/all.js +5 -0
- package/test/body-generator.js +3 -3
- package/test/httpClient.js +3 -3
- package/test/integration.js +47 -12
- package/test/latency.js +29 -25
- package/test/loadtest.js +7 -7
- package/test/request-generator.js +3 -3
- package/test/result.js +1 -1
- package/test/tcpClient.js +23 -0
- package/test/websocket.js +3 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# These are supported funding model platforms
|
|
2
|
+
|
|
3
|
+
github: alexfernandez
|
|
4
|
+
patreon: # Replace with a single Patreon username
|
|
5
|
+
open_collective: # Replace with a single Open Collective username
|
|
6
|
+
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
8
|
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
+
liberapay: # Replace with a single Liberapay username
|
|
10
|
+
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
+
otechie: # Replace with a single Otechie username
|
|
12
|
+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
13
|
+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ but the resulting figure is much more robust.
|
|
|
77
77
|
Using the provided API it is very easy to integrate loadtest with your package, and run programmatic load tests.
|
|
78
78
|
loadtest makes it very easy to run load tests as part of systems tests, before deploying a new version of your software.
|
|
79
79
|
The result includes mean response times and percentiles,
|
|
80
|
-
so that you can abort deployment e.g. if 99% of
|
|
80
|
+
so that you can abort deployment e.g. if 99% of all requests don't finish in 10 ms or less.
|
|
81
81
|
|
|
82
82
|
### Usage Don'ts
|
|
83
83
|
|
|
@@ -85,14 +85,18 @@ so that you can abort deployment e.g. if 99% of the requests don't finish in 10
|
|
|
85
85
|
but it is still limited.
|
|
86
86
|
`loadtest` saturates a single CPU pretty quickly,
|
|
87
87
|
so it uses half the available cores in your processor.
|
|
88
|
-
|
|
89
|
-
which happens approx. when your load is above 4000~
|
|
90
|
-
please adjust the number of cores.
|
|
88
|
+
The Node.js processes can reach 100% usage in `top`,
|
|
89
|
+
which happens approx. when your load is above 4000~7000 rps per core.
|
|
90
|
+
In this case please adjust the number of cores.
|
|
91
91
|
So for instance with eight cores you can expect to get a maximum performance of
|
|
92
|
-
8 * 5000
|
|
93
|
-
|
|
92
|
+
8 * 5000 = 40 krps.
|
|
93
|
+
|
|
94
|
+
You can measure the practical limits of `loadtest` on your specific test machines by running it against a simple
|
|
94
95
|
[test server](#test-server)
|
|
95
|
-
and seeing when it reaches 100% CPU.
|
|
96
|
+
and seeing when it reaches 100% CPU. Run the following commands on two different consoles:
|
|
97
|
+
|
|
98
|
+
$ node bin/testserver.js
|
|
99
|
+
$ node bin/loadtest.js -n 1000000 -c 100 http://localhost:7357/
|
|
96
100
|
|
|
97
101
|
If you have reached the limits of `loadtest` even after using all cores,
|
|
98
102
|
there are other tools that you can try.
|
|
@@ -100,7 +104,7 @@ there are other tools that you can try.
|
|
|
100
104
|
* [AutoCannon](https://www.npmjs.com/package/autocannon): also an `npm` package,
|
|
101
105
|
awesome tool with an interface similar to `wrk`.
|
|
102
106
|
* [Apache `ab`](http://httpd.apache.org/docs/2.2/programs/ab.html)
|
|
103
|
-
has great performance, but it is
|
|
107
|
+
has great performance, but it is limited by a single CPU performance.
|
|
104
108
|
Its practical limit is somewhere around ~40 krps.
|
|
105
109
|
* [weighttp](http://redmine.lighttpd.net/projects/weighttp/wiki) is also `ab`-compatible
|
|
106
110
|
and is supposed to be very fast (the author has not personally used it).
|
|
@@ -112,43 +116,57 @@ It may need installing from source though, and its interface is not `ab`-compati
|
|
|
112
116
|
|
|
113
117
|
The following parameters are compatible with Apache ab.
|
|
114
118
|
|
|
115
|
-
#### `-
|
|
119
|
+
#### `-t`, `--maxSeconds`
|
|
120
|
+
|
|
121
|
+
Max number of seconds to wait until requests no longer go out.
|
|
122
|
+
Default is 10 seconds, applies only if no `--maxRequests` is specified.
|
|
123
|
+
|
|
124
|
+
Note: this is different than Apache `ab`, which stops _receiving_ requests after the given seconds.
|
|
125
|
+
|
|
126
|
+
**Warning**: max seconds used to have no default value,
|
|
127
|
+
so tests would run indefinitely if no `--maxSeconds` and no `--maxRequests` were specified.
|
|
128
|
+
Max seconds was changed to default to 10 in version 8.
|
|
129
|
+
|
|
130
|
+
#### `-n`, `--maxRequests`
|
|
116
131
|
|
|
117
132
|
Number of requests to send out.
|
|
118
|
-
Default is no limit;
|
|
133
|
+
Default is no limit;
|
|
134
|
+
will keep on sending until the time limit in `--maxSeconds` is reached.
|
|
119
135
|
|
|
120
136
|
Note: the total number of requests sent can be bigger than the parameter if there is a concurrency parameter;
|
|
121
137
|
loadtest will report just the first `n`.
|
|
122
138
|
|
|
123
|
-
#### `-c concurrency`
|
|
139
|
+
#### `-c`, `--concurrency`
|
|
124
140
|
|
|
125
141
|
loadtest will create a certain number of clients; this parameter controls how many.
|
|
126
142
|
Requests from them will arrive concurrently to the server.
|
|
127
|
-
Default value is
|
|
143
|
+
Default value is 10.
|
|
128
144
|
|
|
129
145
|
Note: requests are not sent in parallel (from different processes),
|
|
130
146
|
but concurrently (a second request may be sent before the first has been answered).
|
|
147
|
+
Does not apply if `--requestsPerSecond` is specified.
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
Default is no limit; will keep on sending if not specified.
|
|
149
|
+
Beware: if concurrency is too low then it is possible that there will not be enough clients
|
|
150
|
+
to send all the supported traffic,
|
|
151
|
+
adjust it with `-c` if needed.
|
|
136
152
|
|
|
137
|
-
|
|
153
|
+
**Warning**: concurrency used to have a default value of 1,
|
|
154
|
+
until it was changed to 10 in version 8.
|
|
138
155
|
|
|
139
|
-
#### `-k
|
|
156
|
+
#### `-k`, `--keepalive`
|
|
140
157
|
|
|
141
|
-
Open connections using keep-alive:
|
|
158
|
+
Open connections using keep-alive:
|
|
159
|
+
use header `Connection: keep-alive` instead of `Connection: close`.
|
|
142
160
|
|
|
143
161
|
Note: Uses [agentkeepalive](https://npmjs.org/package/agentkeepalive),
|
|
144
162
|
which performs better than the default node.js agent.
|
|
145
163
|
|
|
146
|
-
#### `-C cookie-name=value`
|
|
164
|
+
#### `-C`, `--cookie cookie-name=value`
|
|
147
165
|
|
|
148
166
|
Send a cookie with the request. The cookie `name=value` is then sent to the server.
|
|
149
167
|
This parameter can be repeated as many times as needed.
|
|
150
168
|
|
|
151
|
-
#### `-H header:value`
|
|
169
|
+
#### `-H`, `--header header:value`
|
|
152
170
|
|
|
153
171
|
Send a custom header with the request. The line `header:value` is then sent to the server.
|
|
154
172
|
This parameter can be repeated as many times as needed.
|
|
@@ -168,19 +186,19 @@ Note: if you need to add a header with spaces, be sure to surround both header a
|
|
|
168
186
|
|
|
169
187
|
$ loadtest -H "Authorization: Basic xxx=="
|
|
170
188
|
|
|
171
|
-
#### `-T
|
|
189
|
+
#### `-T`, `--contentType`
|
|
172
190
|
|
|
173
191
|
Set the MIME content type for POST data. Default: `text/plain`.
|
|
174
192
|
|
|
175
|
-
#### `-P
|
|
193
|
+
#### `-P`, `--postBody`
|
|
176
194
|
|
|
177
195
|
Send the string as the POST body. E.g.: `-P '{"key": "a9acf03f"}'`
|
|
178
196
|
|
|
179
|
-
#### `-A
|
|
197
|
+
#### `-A`, `--patchBody`
|
|
180
198
|
|
|
181
199
|
Send the string as the PATCH body. E.g.: `-A '{"key": "a9acf03f"}'`
|
|
182
200
|
|
|
183
|
-
#### `-m method`
|
|
201
|
+
#### `-m`, `--method`
|
|
184
202
|
|
|
185
203
|
Set method that will be sent to the test URL.
|
|
186
204
|
Accepts: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`,
|
|
@@ -194,7 +212,7 @@ Requires setting the method with `-m` and the type with `-T`.
|
|
|
194
212
|
Example: `--data '{"username": "test", "password": "test"}' -T 'application/x-www-form-urlencoded' -m POST`
|
|
195
213
|
|
|
196
214
|
|
|
197
|
-
#### `-p
|
|
215
|
+
#### `-p`, `--postFile`
|
|
198
216
|
|
|
199
217
|
Send the data contained in the given file in the POST body.
|
|
200
218
|
Remember to set `-T` to the correct content-type.
|
|
@@ -218,7 +236,7 @@ export default function request(requestId) {
|
|
|
218
236
|
|
|
219
237
|
See sample file in `sample/post-file.js`, and test in `test/body-generator.js`.
|
|
220
238
|
|
|
221
|
-
#### `-u
|
|
239
|
+
#### `-u`, `--putFile`
|
|
222
240
|
|
|
223
241
|
Send the data contained in the given file as a PUT request.
|
|
224
242
|
Remember to set `-T` to the correct content-type.
|
|
@@ -229,7 +247,7 @@ to provide the body of each request.
|
|
|
229
247
|
This is useful if you want to generate request bodies dynamically and vary them for each request.
|
|
230
248
|
For examples see above for `-p`.
|
|
231
249
|
|
|
232
|
-
#### `-a
|
|
250
|
+
#### `-a`, `--patchFile`
|
|
233
251
|
|
|
234
252
|
Send the data contained in the given file as a PATCH request.
|
|
235
253
|
Remember to set `-T` to the correct content-type.
|
|
@@ -240,12 +258,12 @@ to provide the body of each request.
|
|
|
240
258
|
This is useful if you want to generate request bodies dynamically and vary them for each request.
|
|
241
259
|
For examples see above for `-p`.
|
|
242
260
|
|
|
243
|
-
##### `-r recover`
|
|
261
|
+
##### `-r`, `--recover`
|
|
244
262
|
|
|
245
263
|
Recover from errors. Always active: loadtest does not stop on errors.
|
|
246
264
|
After the tests are finished, if there were errors a report with all error codes will be shown.
|
|
247
265
|
|
|
248
|
-
#### `-s secureProtocol`
|
|
266
|
+
#### `-s`, `--secureProtocol`
|
|
249
267
|
|
|
250
268
|
The TLS/SSL method to use. (e.g. TLSv1_method)
|
|
251
269
|
|
|
@@ -253,7 +271,7 @@ Example:
|
|
|
253
271
|
|
|
254
272
|
$ loadtest -n 1000 -s TLSv1_method https://www.example.com
|
|
255
273
|
|
|
256
|
-
#### `-V version`
|
|
274
|
+
#### `-V`, `--version`
|
|
257
275
|
|
|
258
276
|
Show version number and exit.
|
|
259
277
|
|
|
@@ -261,25 +279,17 @@ Show version number and exit.
|
|
|
261
279
|
|
|
262
280
|
The following parameters are _not_ compatible with Apache ab.
|
|
263
281
|
|
|
264
|
-
#### `--rps requestsPerSecond`
|
|
282
|
+
#### `--rps`, `--requestsPerSecond`
|
|
265
283
|
|
|
266
284
|
Controls the number of requests per second that are sent.
|
|
267
285
|
Cannot be fractional, e.g. `--rps 0.5`.
|
|
268
286
|
In this mode each request is not sent as soon as the previous one is responded,
|
|
269
287
|
but periodically even if previous requests have not been responded yet.
|
|
270
288
|
|
|
271
|
-
Note:
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
loadtest <url> -c 10 --rps 10
|
|
275
|
-
|
|
276
|
-
will send a total of 10 rps to the given URL, from 10 different clients
|
|
277
|
-
(each client will send 1 request per second).
|
|
278
|
-
|
|
279
|
-
Beware: if concurrency is too low then it is possible that there will not be enough clients
|
|
280
|
-
to send all of the rps, adjust it with `-c` if needed.
|
|
289
|
+
Note: the `--concurrency` option will be ignored if `--requestsPerSecond` is specified;
|
|
290
|
+
clients will be created on demand.
|
|
281
291
|
|
|
282
|
-
Note:
|
|
292
|
+
Note: `--rps` is not supported for websockets.
|
|
283
293
|
|
|
284
294
|
#### `--cores number`
|
|
285
295
|
|
|
@@ -306,7 +316,7 @@ Setting this to 0 disables timeout (default).
|
|
|
306
316
|
#### `-R requestGeneratorModule.js`
|
|
307
317
|
|
|
308
318
|
Use a custom request generator function from an external file.
|
|
309
|
-
See an example of a request generator module in [
|
|
319
|
+
See an example of a request generator module in [`requestGenerator`](doc/api.md#requestGenerator).
|
|
310
320
|
Also see [`sample/request-generator.js`](sample/request-generator.js) for some sample code including a body
|
|
311
321
|
(or [`sample/request-generator.ts`](sample/request-generator.ts) for ES6/TypeScript).
|
|
312
322
|
|
|
@@ -338,6 +348,16 @@ Sets the certificate for the http client to use. Must be used with `--key`.
|
|
|
338
348
|
|
|
339
349
|
Sets the key for the http client to use. Must be used with `--cert`.
|
|
340
350
|
|
|
351
|
+
#### `--tcp` (experimental)
|
|
352
|
+
|
|
353
|
+
Option to use low level TCP sockets,
|
|
354
|
+
faster than the standard HTTP library.
|
|
355
|
+
Not all options are supported.
|
|
356
|
+
|
|
357
|
+
**Warning**: experimental option.
|
|
358
|
+
May not work with your test case.
|
|
359
|
+
See [TCP Sockets Performance](doc/tcp-sockets.md) for details.
|
|
360
|
+
|
|
341
361
|
### Test Server
|
|
342
362
|
|
|
343
363
|
loadtest bundles a test server. To run it:
|
|
@@ -403,7 +423,7 @@ with concurrency 10 (only relevant results are shown):
|
|
|
403
423
|
Requests per second: 368
|
|
404
424
|
Total time: 44.503181166000005 s
|
|
405
425
|
|
|
406
|
-
Percentage of
|
|
426
|
+
Percentage of requests served within a certain time
|
|
407
427
|
50% 4 ms
|
|
408
428
|
90% 5 ms
|
|
409
429
|
95% 6 ms
|
|
@@ -420,7 +440,7 @@ Now we will try a fixed rate of 1000 rps:
|
|
|
420
440
|
Requests: 9546, requests per second: 1000, mean latency: 0 ms
|
|
421
441
|
Requests: 14549, requests per second: 1000, mean latency: 20 ms
|
|
422
442
|
...
|
|
423
|
-
Percentage of
|
|
443
|
+
Percentage of requests served within a certain time
|
|
424
444
|
50% 1 ms
|
|
425
445
|
90% 2 ms
|
|
426
446
|
95% 8 ms
|
|
@@ -451,7 +471,7 @@ Let us lower the rate to 500 rps:
|
|
|
451
471
|
Requests per second: 488
|
|
452
472
|
Total time: 20.002735398000002 s
|
|
453
473
|
|
|
454
|
-
Percentage of
|
|
474
|
+
Percentage of requests served within a certain time
|
|
455
475
|
50% 1 ms
|
|
456
476
|
90% 1 ms
|
|
457
477
|
95% 1 ms
|
|
@@ -474,7 +494,7 @@ The result (with the same test server) is impressive:
|
|
|
474
494
|
...
|
|
475
495
|
Requests per second: 4099
|
|
476
496
|
|
|
477
|
-
Percentage of
|
|
497
|
+
Percentage of requests served within a certain time
|
|
478
498
|
50% 2 ms
|
|
479
499
|
90% 3 ms
|
|
480
500
|
95% 3 ms
|
|
@@ -487,7 +507,7 @@ Now we're talking! The steady rate also goes up to 2 krps:
|
|
|
487
507
|
...
|
|
488
508
|
Requests per second: 1950
|
|
489
509
|
|
|
490
|
-
Percentage of
|
|
510
|
+
Percentage of requests served within a certain time
|
|
491
511
|
50% 1 ms
|
|
492
512
|
90% 2 ms
|
|
493
513
|
95% 2 ms
|
|
@@ -567,6 +587,8 @@ see [doc/api.md](doc/api.md) for details.
|
|
|
567
587
|
* `percent`: return error only for the given % of requests.
|
|
568
588
|
* `logger(request, response)`: function to call after every request.
|
|
569
589
|
|
|
590
|
+
Returns a test server that you can `close()` when finished.
|
|
591
|
+
|
|
570
592
|
### Configuration file
|
|
571
593
|
|
|
572
594
|
It is possible to put configuration options in a file named `.loadtestrc` in your working directory or in a file whose name is specified in the `loadtest` entry of your `package.json`. The options in the file will be used only if they are not specified in the command line.
|
package/bin/loadtest.js
CHANGED
|
@@ -9,9 +9,9 @@ import {getHalfCores} from '../lib/cluster.js'
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
const options = stdio.getopt({
|
|
12
|
+
maxSeconds: {key: 't', args: 1, description: 'Max time in seconds to wait for responses, default 10'},
|
|
12
13
|
maxRequests: {key: 'n', args: 1, description: 'Number of requests to perform'},
|
|
13
|
-
concurrency: {key: 'c', args: 1, description: 'Number of requests
|
|
14
|
-
maxSeconds: {key: 't', args: 1, description: 'Max time in seconds to wait for responses'},
|
|
14
|
+
concurrency: {key: 'c', args: 1, description: 'Number of concurrent requests, default 10'},
|
|
15
15
|
timeout: {key: 'd', args: 1, description: 'Timeout for each request in milliseconds'},
|
|
16
16
|
contentType: {key: 'T', args: 1, description: 'MIME type for the body'},
|
|
17
17
|
cookies: {key: 'C', multiple: true, description: 'Send a cookie as name=value'},
|
|
@@ -36,6 +36,7 @@ const options = stdio.getopt({
|
|
|
36
36
|
cert: {args: 1, description: 'The client certificate to use'},
|
|
37
37
|
quiet: {description: 'Do not log any messages'},
|
|
38
38
|
cores: {args: 1, description: 'Number of cores to use', default: getHalfCores()},
|
|
39
|
+
tcp: {description: 'Use TCP sockets (experimental)'},
|
|
39
40
|
agent: {description: 'Use a keep-alive http agent (deprecated)'},
|
|
40
41
|
debug: {description: 'Show debug messages (deprecated)'},
|
|
41
42
|
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {loadTest, startServer} from '../index.js'
|
|
2
|
+
|
|
3
|
+
const port = 7359;
|
|
4
|
+
const serverOptions = {port}
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
async function runTcpPerformanceTest() {
|
|
8
|
+
const server = await startServer(serverOptions)
|
|
9
|
+
const options = {
|
|
10
|
+
url: `http://localhost:${port}`,
|
|
11
|
+
method: 'GET',
|
|
12
|
+
tcp: true,
|
|
13
|
+
};
|
|
14
|
+
const result = await loadTest(options)
|
|
15
|
+
await server.close()
|
|
16
|
+
console.log(`Requests received: ${server.totalRequests}`)
|
|
17
|
+
result.show()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
await runTcpPerformanceTest()
|
|
21
|
+
|
package/bin/testserver.js
CHANGED
|
@@ -5,49 +5,51 @@ import {startServer} from '../lib/testserver.js'
|
|
|
5
5
|
import {loadConfig} from '../lib/config.js'
|
|
6
6
|
import {getHalfCores, runTask} from '../lib/cluster.js'
|
|
7
7
|
|
|
8
|
+
const configuration = loadConfig()
|
|
8
9
|
const options = readOptions()
|
|
9
10
|
start(options)
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
function readOptions() {
|
|
13
14
|
const options = stdio.getopt({
|
|
15
|
+
port: {key: 'p', args: 1, description: 'Port for the server'},
|
|
14
16
|
delay: {key: 'd', args: 1, description: 'Delay the response for the given milliseconds'},
|
|
15
17
|
error: {key: 'e', args: 1, description: 'Return an HTTP error code'},
|
|
16
|
-
percent: {key: '
|
|
17
|
-
cores: {key: 'c', args: 1, description: 'Number of cores to use, default is half the total', default: getHalfCores()}
|
|
18
|
+
percent: {key: 'P', args: 1, description: 'Return an error (default 500) only for some % of requests'},
|
|
19
|
+
cores: {key: 'c', args: 1, description: 'Number of cores to use, default is half the total', default: getHalfCores()},
|
|
20
|
+
body: {key: 'b', args: 1, description: 'Body to return, default "OK"'},
|
|
21
|
+
file: {key: 'f', args: 1, description: 'File to read and return as body'},
|
|
18
22
|
});
|
|
19
|
-
const configuration = loadConfig()
|
|
20
23
|
if (options.args && options.args.length == 1) {
|
|
21
|
-
options.port =
|
|
22
|
-
if (!options.port) {
|
|
23
|
-
console.error('Invalid port');
|
|
24
|
-
options.printHelp();
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
24
|
+
options.port = options.port || options.args[0]
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
return {
|
|
27
|
+
port: readInt(options, 'port'),
|
|
28
|
+
delay: readInt(options, 'delay'),
|
|
29
|
+
error: readInt(options, 'error'),
|
|
30
|
+
percent: readInt(options, 'percent'),
|
|
31
|
+
cores: readInt(options, 'cores'),
|
|
32
|
+
body: readString(options, 'body'),
|
|
33
|
+
file: readString(options, 'file'),
|
|
35
34
|
}
|
|
35
|
+
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
options.
|
|
37
|
+
function readString(options, key) {
|
|
38
|
+
return options[key] || configuration[key]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function readInt(options, key) {
|
|
42
|
+
if (options[key] && isNaN(options[key])) {
|
|
43
|
+
console.error(`Invalid ${key}`);
|
|
44
|
+
options.printHelp();
|
|
45
|
+
process.exit(1);
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
+
const value = readString(options, key)
|
|
48
|
+
return parseInt(value) || undefined
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
function start(options) {
|
|
50
|
-
runTask(options.cores, async () => await startServer(options))
|
|
52
|
+
runTask(options.cores, async () => {await startServer(options)})
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
|
package/doc/api.md
CHANGED
|
@@ -37,7 +37,7 @@ result.show()
|
|
|
37
37
|
console.log('Tests run successfully')
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
The call returns a `Result` object that contains all info about the load test, also described below.
|
|
40
|
+
The call returns a `Result` object that contains all info about the load test, also described [below](#result).
|
|
41
41
|
Call `result.show()` to display the results in the standard format on the console.
|
|
42
42
|
|
|
43
43
|
As a legacy from before promises existed,
|
|
@@ -61,46 +61,6 @@ loadTest(options, function(error, result) {
|
|
|
61
61
|
})
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
Beware: if there are no `maxRequests` and no `maxSeconds`, then tests will run forever
|
|
66
|
-
and will not call the callback.
|
|
67
|
-
|
|
68
|
-
### Result
|
|
69
|
-
|
|
70
|
-
The latency result returned at the end of the load test contains a full set of data, including:
|
|
71
|
-
mean latency, number of errors and percentiles.
|
|
72
|
-
A simplified example follows:
|
|
73
|
-
|
|
74
|
-
```javascript
|
|
75
|
-
{
|
|
76
|
-
url: 'http://localhost:80/',
|
|
77
|
-
maxRequests: 1000,
|
|
78
|
-
maxSeconds: 0,
|
|
79
|
-
concurrency: 10,
|
|
80
|
-
agent: 'none',
|
|
81
|
-
requestsPerSecond: undefined,
|
|
82
|
-
totalRequests: 1000,
|
|
83
|
-
percentiles: {
|
|
84
|
-
'50': 7,
|
|
85
|
-
'90': 10,
|
|
86
|
-
'95': 11,
|
|
87
|
-
'99': 15
|
|
88
|
-
},
|
|
89
|
-
effectiveRps: 2824,
|
|
90
|
-
elapsedSeconds: 0.354108,
|
|
91
|
-
meanLatencyMs: 7.72,
|
|
92
|
-
maxLatencyMs: 20,
|
|
93
|
-
totalErrors: 3,
|
|
94
|
-
errorCodes: {
|
|
95
|
-
'0': 1,
|
|
96
|
-
'500': 2
|
|
97
|
-
},
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
The `result` object also has a `result.show()` function
|
|
102
|
-
that displays the results on the console in the standard format.
|
|
103
|
-
|
|
104
64
|
### Options
|
|
105
65
|
|
|
106
66
|
All options but `url` are, as their name implies, optional.
|
|
@@ -110,23 +70,34 @@ See also the [simplified list](../README.md#loadtest-parameters).
|
|
|
110
70
|
|
|
111
71
|
The URL to invoke. Mandatory.
|
|
112
72
|
|
|
113
|
-
#### `
|
|
73
|
+
#### `maxSeconds`
|
|
114
74
|
|
|
115
|
-
|
|
75
|
+
Max number of seconds to run the tests.
|
|
76
|
+
Default is 10 seconds, applies only if no `maxRequests` is specified.
|
|
77
|
+
|
|
78
|
+
Note: after the given number of seconds `loadtest` will stop sending requests,
|
|
79
|
+
but may continue receiving tests afterwards.
|
|
80
|
+
|
|
81
|
+
**Warning**: max seconds used to have no default value,
|
|
82
|
+
so tests would run indefinitely if no `maxSeconds` and no `maxRequests` were specified.
|
|
83
|
+
Max seconds was changed to default to 10 in version 8.
|
|
116
84
|
|
|
117
85
|
#### `maxRequests`
|
|
118
86
|
|
|
119
87
|
A max number of requests; after they are reached the test will end.
|
|
88
|
+
Default is no limit;
|
|
89
|
+
will keep on sending until the time limit in `maxSeconds` is reached.
|
|
120
90
|
|
|
121
91
|
Note: the actual number of requests sent can be bigger if there is a concurrency level;
|
|
122
92
|
loadtest will report just on the max number of requests.
|
|
123
93
|
|
|
124
|
-
#### `
|
|
94
|
+
#### `concurrency`
|
|
125
95
|
|
|
126
|
-
|
|
96
|
+
How many clients to start in parallel, default is 10.
|
|
97
|
+
Does not apply if `requestsPerSecond` is specified.
|
|
127
98
|
|
|
128
|
-
|
|
129
|
-
|
|
99
|
+
**Warning**: concurrency used to have a default value of 1,
|
|
100
|
+
until it was changed to 10 in version 8.
|
|
130
101
|
|
|
131
102
|
#### `timeout`
|
|
132
103
|
|
|
@@ -134,7 +105,7 @@ Timeout for each generated request in milliseconds. Setting this to 0 disables t
|
|
|
134
105
|
|
|
135
106
|
#### `cookies`
|
|
136
107
|
|
|
137
|
-
An array of cookies to send. Each cookie should be a string of the form name=value
|
|
108
|
+
An array of cookies to send. Each cookie should be a string of the form `name=value`.
|
|
138
109
|
|
|
139
110
|
#### `headers`
|
|
140
111
|
|
|
@@ -146,9 +117,6 @@ like this:
|
|
|
146
117
|
accept: "text/plain;text/html"
|
|
147
118
|
}
|
|
148
119
|
|
|
149
|
-
Note: when using the API, the "host" header is not inferred from the URL but needs to be sent
|
|
150
|
-
explicitly.
|
|
151
|
-
|
|
152
120
|
#### `method`
|
|
153
121
|
|
|
154
122
|
The method to use: POST, PUT. Default: GET.
|
|
@@ -317,6 +285,86 @@ function contentInspector(result) {
|
|
|
317
285
|
}
|
|
318
286
|
},
|
|
319
287
|
```
|
|
288
|
+
|
|
289
|
+
#### `tcp`
|
|
290
|
+
|
|
291
|
+
If true, use low-level TCP sockets.
|
|
292
|
+
Faster option that can increase performance by up to 10x,
|
|
293
|
+
especially in local test setups.
|
|
294
|
+
|
|
295
|
+
**Warning**: Experimental option.
|
|
296
|
+
May not work for your test case.
|
|
297
|
+
Not compatible with options `indexParam`, `statusCallback`, `requestGenerator`.
|
|
298
|
+
See [TCP Sockets Performance](doc/tcp-sockets.md) for details.
|
|
299
|
+
|
|
300
|
+
### Result
|
|
301
|
+
|
|
302
|
+
The latency result returned at the end of the load test contains a full set of data, including:
|
|
303
|
+
mean latency, number of errors and percentiles.
|
|
304
|
+
A simplified example follows:
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
{
|
|
308
|
+
url: 'http://localhost:80/',
|
|
309
|
+
maxRequests: 1000,
|
|
310
|
+
maxSeconds: 0,
|
|
311
|
+
concurrency: 10,
|
|
312
|
+
agent: 'none',
|
|
313
|
+
requestsPerSecond: undefined,
|
|
314
|
+
totalRequests: 1000,
|
|
315
|
+
percentiles: {
|
|
316
|
+
'50': 7,
|
|
317
|
+
'90': 10,
|
|
318
|
+
'95': 11,
|
|
319
|
+
'99': 15
|
|
320
|
+
},
|
|
321
|
+
effectiveRps: 2824,
|
|
322
|
+
elapsedSeconds: 0.354108,
|
|
323
|
+
meanLatencyMs: 7.72,
|
|
324
|
+
maxLatencyMs: 20,
|
|
325
|
+
totalErrors: 3,
|
|
326
|
+
clients: 10,
|
|
327
|
+
errorCodes: {
|
|
328
|
+
'0': 1,
|
|
329
|
+
'500': 2
|
|
330
|
+
},
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The `result` object also has a `result.show()` function
|
|
335
|
+
that displays the results on the console in the standard format.
|
|
336
|
+
|
|
337
|
+
Some of the attributes (`url`, `concurrency`) will be identical to the parameters passed.
|
|
338
|
+
The following attributes can also be returned.
|
|
339
|
+
|
|
340
|
+
#### `totalRequests`
|
|
341
|
+
|
|
342
|
+
How many requests were actually processed.
|
|
343
|
+
|
|
344
|
+
#### `totalRequests`
|
|
345
|
+
|
|
346
|
+
How many requests resulted in an error.
|
|
347
|
+
|
|
348
|
+
#### `effectiveRps`
|
|
349
|
+
|
|
350
|
+
How many requests per second were actually processed.
|
|
351
|
+
|
|
352
|
+
#### `elapsedSeconds`
|
|
353
|
+
|
|
354
|
+
How many seconds the test lasted.
|
|
355
|
+
|
|
356
|
+
#### `meanLatencyMs`
|
|
357
|
+
|
|
358
|
+
Average latency in milliseconds.
|
|
359
|
+
|
|
360
|
+
#### `errorCodes`
|
|
361
|
+
|
|
362
|
+
Object containing a map with all status codes received.
|
|
363
|
+
|
|
364
|
+
#### `clients`
|
|
365
|
+
|
|
366
|
+
Number of concurrent clients started.
|
|
367
|
+
Should equal the concurrency level unless the `rps` option is specified.
|
|
320
368
|
|
|
321
369
|
### Start Test Server
|
|
322
370
|
|
|
@@ -330,7 +378,7 @@ await server.close()
|
|
|
330
378
|
```
|
|
331
379
|
|
|
332
380
|
This function returns when the server is up and running,
|
|
333
|
-
with
|
|
381
|
+
with a server object which can be `close()`d when it is no longer useful.
|
|
334
382
|
As a legacy from before promises existed,
|
|
335
383
|
if an optional callback is passed as second parameter then it will not behave as `async`:
|
|
336
384
|
|
|
@@ -338,6 +386,9 @@ if an optional callback is passed as second parameter then it will not behave as
|
|
|
338
386
|
const server = startServer({port: 8000}, error => console.error(error))
|
|
339
387
|
```
|
|
340
388
|
|
|
389
|
+
**Warning**: up until version 7 this function returned an HTTP server;
|
|
390
|
+
this was changed to a test server object with an identical `close()` method.
|
|
391
|
+
|
|
341
392
|
The following options are available.
|
|
342
393
|
|
|
343
394
|
#### `port`
|