diff options
author | Andrey Pechkurov <apechkurov@gmail.com> | 2020-12-23 16:52:44 +0300 |
---|---|---|
committer | Danielle Adams <adamzdanielle@gmail.com> | 2021-01-12 15:09:25 +0300 |
commit | 7aedda9dcdd01d6172a187a57e8ad74fda71d4b0 (patch) | |
tree | 772d65ffb9ea8688089608a87495fa92b98042cf /benchmark | |
parent | 822ac482728c12882323082aa1dea3defc0a74fa (diff) |
benchmark: add simple https benchmark
Adds a simple benchmark for https server based on the http simple
benchmark. Updates benchmarker integration for autocannon and wrk,
so that they support https scheme.
Also adds a new HTTPS section and improves HTTP/2 section in
the benchmark guide.
PR-URL: https://github.com/nodejs/node/pull/36612
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Diffstat (limited to 'benchmark')
-rw-r--r-- | benchmark/_http-benchmarkers.js | 14 | ||||
-rw-r--r-- | benchmark/_test-double-benchmarker.js | 15 | ||||
-rw-r--r-- | benchmark/fixtures/simple-https-server.js | 72 | ||||
-rw-r--r-- | benchmark/https/simple.js | 29 |
4 files changed, 122 insertions, 8 deletions
diff --git a/benchmark/_http-benchmarkers.js b/benchmark/_http-benchmarkers.js index d0f192e7594..f25bcd31988 100644 --- a/benchmark/_http-benchmarkers.js +++ b/benchmark/_http-benchmarkers.js @@ -29,7 +29,8 @@ class AutocannonBenchmarker { for (const field in options.headers) { args.push('-H', `${field}=${options.headers[field]}`); } - args.push(`http://127.0.0.1:${options.port}${options.path}`); + const scheme = options.scheme || 'http'; + args.push(`${scheme}://127.0.0.1:${options.port}${options.path}`); const child = child_process.spawn(this.executable, args); return child; } @@ -60,11 +61,12 @@ class WrkBenchmarker { const duration = typeof options.duration === 'number' ? Math.max(options.duration, 1) : options.duration; + const scheme = options.scheme || 'http'; const args = [ '-d', duration, '-c', options.connections, '-t', Math.min(options.connections, require('os').cpus().length || 8), - `http://127.0.0.1:${options.port}${options.path}`, + `${scheme}://127.0.0.1:${options.port}${options.path}`, ]; for (const field in options.headers) { args.push('-H', `${field}: ${options.headers[field]}`); @@ -90,8 +92,8 @@ class WrkBenchmarker { */ class TestDoubleBenchmarker { constructor(type) { - // `type` is the type of benchmarker. Possible values are 'http' and - // 'http2'. + // `type` is the type of benchmarker. Possible values are 'http', 'https', + // and 'http2'. this.name = `test-double-${type}`; this.executable = path.resolve(__dirname, '_test-double-benchmarker.js'); this.present = fs.existsSync(this.executable); @@ -101,8 +103,9 @@ class TestDoubleBenchmarker { create(options) { process.env.duration = process.env.duration || options.duration || 5; + const scheme = options.scheme || 'http'; const env = { - test_url: `http://127.0.0.1:${options.port}${options.path}`, + test_url: `${scheme}://127.0.0.1:${options.port}${options.path}`, ...process.env }; @@ -179,6 +182,7 @@ const http_benchmarkers = [ new WrkBenchmarker(), new AutocannonBenchmarker(), new TestDoubleBenchmarker('http'), + new TestDoubleBenchmarker('https'), new TestDoubleBenchmarker('http2'), new H2LoadBenchmarker(), ]; diff --git a/benchmark/_test-double-benchmarker.js b/benchmark/_test-double-benchmarker.js index 60264dfd46a..89843d4616c 100644 --- a/benchmark/_test-double-benchmarker.js +++ b/benchmark/_test-double-benchmarker.js @@ -1,10 +1,15 @@ 'use strict'; const myModule = process.argv[2]; -if (!['http', 'http2'].includes(myModule)) { +if (!['http', 'https', 'http2'].includes(myModule)) { throw new Error(`Invalid module for benchmark test double: ${myModule}`); } +let options; +if (myModule === 'https') { + options = { rejectUnauthorized: false }; +} + const http = require(myModule); const duration = +process.env.duration; @@ -33,8 +38,12 @@ function request(res, client) { } function run() { - if (http.get) { // HTTP - http.get(url, request); + if (http.get) { // HTTP or HTTPS + if (options) { + http.get(url, options, request); + } else { + http.get(url, request); + } } else { // HTTP/2 const client = http.connect(url); client.on('error', (e) => { throw e; }); diff --git a/benchmark/fixtures/simple-https-server.js b/benchmark/fixtures/simple-https-server.js new file mode 100644 index 00000000000..d3b07a11011 --- /dev/null +++ b/benchmark/fixtures/simple-https-server.js @@ -0,0 +1,72 @@ +'use strict'; + +const fixtures = require('../../test/common/fixtures'); +const https = require('https'); + +const options = { + key: fixtures.readKey('rsa_private.pem'), + cert: fixtures.readKey('rsa_cert.crt') +}; + +const storedBytes = Object.create(null); +const storedBuffer = Object.create(null); + +module.exports = https.createServer(options, (req, res) => { + // URL format: /<type>/<length>/<chunks>/chunkedEnc + const params = req.url.split('/'); + const command = params[1]; + let body = ''; + const arg = params[2]; + const n_chunks = parseInt(params[3], 10); + const chunkedEnc = params.length >= 5 && params[4] === '0' ? false : true; + let status = 200; + + let n, i; + if (command === 'bytes') { + n = ~~arg; + if (n <= 0) + throw new Error('bytes called with n <= 0'); + if (storedBytes[n] === undefined) { + storedBytes[n] = 'C'.repeat(n); + } + body = storedBytes[n]; + } else if (command === 'buffer') { + n = ~~arg; + if (n <= 0) + throw new Error('buffer called with n <= 0'); + if (storedBuffer[n] === undefined) { + storedBuffer[n] = Buffer.allocUnsafe(n); + for (i = 0; i < n; i++) { + storedBuffer[n][i] = 'C'.charCodeAt(0); + } + } + body = storedBuffer[n]; + } else { + status = 404; + body = 'not found\n'; + } + + // example: https://localhost:port/bytes/512/4 + // sends a 512 byte body in 4 chunks of 128 bytes + const len = body.length; + if (chunkedEnc) { + res.writeHead(status, { + 'Content-Type': 'text/plain', + 'Transfer-Encoding': 'chunked' + }); + } else { + res.writeHead(status, { + 'Content-Type': 'text/plain', + 'Content-Length': len.toString() + }); + } + // send body in chunks + if (n_chunks > 1) { + const step = Math.floor(len / n_chunks) || 1; + for (i = 0, n = (n_chunks - 1); i < n; ++i) + res.write(body.slice(i * step, i * step + step)); + res.end(body.slice((n_chunks - 1) * step)); + } else { + res.end(body); + } +}); diff --git a/benchmark/https/simple.js b/benchmark/https/simple.js new file mode 100644 index 00000000000..243546c346f --- /dev/null +++ b/benchmark/https/simple.js @@ -0,0 +1,29 @@ +'use strict'; +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + type: ['bytes', 'buffer'], + len: [4, 1024, 102400], + chunks: [1, 4], + c: [50, 500], + chunkedEnc: [1, 0], + benchmarker: ['test-double-https'], + duration: 5 +}); + +function main({ type, len, chunks, c, chunkedEnc, duration }) { + const server = require('../fixtures/simple-https-server.js') + .listen(common.PORT) + .on('listening', () => { + const path = `/${type}/${len}/${chunks}/${chunkedEnc}`; + + bench.http({ + path, + connections: c, + scheme: 'https', + duration + }, () => { + server.close(); + }); + }); +} |