diff --git a/README.md b/README.md index e1234a3b0c6..d5cf74b419a 100644 --- a/README.md +++ b/README.md @@ -18,34 +18,31 @@ npm i undici ## Benchmarks The benchmark is a simple `hello world` [example](benchmarks/benchmark.js) using a -number of unix sockets (connections) with a pipelining depth of 10 running on Node 20.6.0. - -### Connections 1 - - -| Tests | Samples | Result | Tolerance | Difference with slowest | -|---------------------|---------|---------------|-----------|-------------------------| -| http - no keepalive | 15 | 5.32 req/sec | ± 2.61 % | - | -| http - keepalive | 10 | 5.35 req/sec | ± 2.47 % | + 0.44 % | -| undici - fetch | 15 | 41.85 req/sec | ± 2.49 % | + 686.04 % | -| undici - pipeline | 40 | 50.36 req/sec | ± 2.77 % | + 845.92 % | -| undici - stream | 15 | 60.58 req/sec | ± 2.75 % | + 1037.72 % | -| undici - request | 10 | 61.19 req/sec | ± 2.60 % | + 1049.24 % | -| undici - dispatch | 20 | 64.84 req/sec | ± 2.81 % | + 1117.81 % | - - -### Connections 50 - -| Tests | Samples | Result | Tolerance | Difference with slowest | -|---------------------|---------|------------------|-----------|-------------------------| -| undici - fetch | 30 | 2107.19 req/sec | ± 2.69 % | - | -| http - no keepalive | 10 | 2698.90 req/sec | ± 2.68 % | + 28.08 % | -| http - keepalive | 10 | 4639.49 req/sec | ± 2.55 % | + 120.17 % | -| undici - pipeline | 40 | 6123.33 req/sec | ± 2.97 % | + 190.59 % | -| undici - stream | 50 | 9426.51 req/sec | ± 2.92 % | + 347.35 % | -| undici - request | 10 | 10162.88 req/sec | ± 2.13 % | + 382.29 % | -| undici - dispatch | 50 | 11191.11 req/sec | ± 2.98 % | + 431.09 % | - +50 TCP connections with a pipelining depth of 10 running on Node 20.6.0. + +│ Tests │ Samples │ Result │ Tolerance │ Difference with slowest │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ got │ 40 │ 1676.51 req/sec │ ± 2.93 % │ - │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ undici - fetch │ 30 │ 2081.23 req/sec │ ± 2.91 % │ + 24.14 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ http - no keepalive │ 30 │ 2477.88 req/sec │ ± 2.73 % │ + 47.80 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ axios │ 20 │ 2673.40 req/sec │ ± 2.54 % │ + 59.46 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ node-fetch │ 10 │ 2776.09 req/sec │ ± 1.16 % │ + 65.59 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ request │ 10 │ 3458.80 req/sec │ ± 0.92 % │ + 106.31 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ http - keepalive │ 40 │ 4415.13 req/sec │ ± 3.00 % │ + 163.35 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ undici - pipeline │ 10 │ 5912.29 req/sec │ ± 3.00 % │ + 252.65 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ undici - request │ 80 │ 7829.95 req/sec │ ± 2.92 % │ + 367.04 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ undici - stream │ 65 │ 8221.08 req/sec │ ± 2.86 % │ + 390.37 % │ +|─────────────────────|─────────|─────────────────|───────────|─────────────────────────| +│ undici - dispatch │ 60 │ 9600.55 req/sec │ ± 2.88 % │ + 472.65 % │ ## Quick Start @@ -62,9 +59,7 @@ const { console.log('response received', statusCode) console.log('headers', headers) -for await (const data of body) { - console.log('data', data) -} +for await (const data of body) { console.log('data', data) } console.log('trailers', trailers) ``` diff --git a/benchmarks/benchmark.js b/benchmarks/benchmark.js index 94ac1b45a81..bdad1efbc4f 100644 --- a/benchmarks/benchmark.js +++ b/benchmarks/benchmark.js @@ -9,6 +9,14 @@ const { isMainThread } = require('worker_threads') const { Pool, Client, fetch, Agent, setGlobalDispatcher } = require('..') +let nodeFetch +const axios = require('axios') +let got + +const util = require('util') +const _request = require('request') +const request = util.promisify(_request) + const iterations = (parseInt(process.env.SAMPLES, 10) || 10) + 1 const errorThreshold = parseInt(process.env.ERROR_THRESHOLD, 10) || 3 const connections = parseInt(process.env.CONNECTIONS, 10) || 50 @@ -269,10 +277,62 @@ if (process.env.PORT) { }).catch(console.log) }) } + + experiments['node-fetch'] = () => { + return makeParallelRequests(resolve => { + nodeFetch(dest.url).then(res => { + res.body.pipe(new Writable({ + write (chunk, encoding, callback) { + callback() + } + })).on('finish', resolve) + }).catch(console.log) + }) + } + + experiments.axios = () => { + return makeParallelRequests(resolve => { + axios.get(dest.url, { responseType: 'stream' }).then(res => { + res.data.pipe(new Writable({ + write (chunk, encoding, callback) { + callback() + } + })).on('finish', resolve) + }).catch(console.log) + }) + } + + experiments.got = () => { + return makeParallelRequests(resolve => { + got.get(dest.url).then(res => { + res.pipe(new Writable({ + write (chunk, encoding, callback) { + callback() + } + })).on('finish', resolve) + }).catch(console.log) + }) + } + + experiments.request = () => { + return makeParallelRequests(resolve => { + request(dest.url).then(res => { + res.pipe(new Writable({ + write (chunk, encoding, callback) { + callback() + } + })).on('finish', resolve) + }).catch(console.log) + }) + } } async function main () { const { cronometro } = await import('cronometro') + const _nodeFetch = await import('node-fetch') + nodeFetch = _nodeFetch.default + const _got = await import('got') + got = _got.default cronometro( experiments, diff --git a/package.json b/package.json index 43d11d25389..2b1e146a683 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "bench": "PORT=3042 concurrently -k -s first npm:bench:server npm:bench:run", "bench:server": "node benchmarks/server.js", "prebench:run": "node benchmarks/wait.js", - "bench:run": "CONNECTIONS=1 node benchmarks/benchmark.js; CONNECTIONS=50 node benchmarks/benchmark.js", + "bench:run": "SAMPLES=100 CONNECTIONS=50 node benchmarks/benchmark.js", "serve:website": "docsify serve .", "prepare": "husky install", "fuzz": "jsfuzz test/fuzzing/fuzz.js corpus" @@ -136,7 +136,11 @@ "tsd": "^0.30.1", "typescript": "^5.0.2", "wait-on": "^7.0.1", - "ws": "^8.11.0" + "ws": "^8.11.0", + "axios": "^1.6.5", + "got": "^14.0.0", + "node-fetch": "^3.3.2", + "request": "^2.88.2" }, "engines": { "node": ">=18.0"