From 962772356ea8220505a2496c33d78bb7c7803a1a Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 16 Aug 2025 11:45:14 +0200 Subject: [PATCH 1/4] chore: replace benchmark with tinybench --- benchmark.js | 127 --------------------------------------------- benchmark.mjs | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 4 +- 3 files changed, 141 insertions(+), 129 deletions(-) delete mode 100644 benchmark.js create mode 100644 benchmark.mjs diff --git a/benchmark.js b/benchmark.js deleted file mode 100644 index 7986cd3..0000000 --- a/benchmark.js +++ /dev/null @@ -1,127 +0,0 @@ -'use strict' - -const benchmark = require('benchmark') -const suite = new benchmark.Suite() -const fasturi = require('./') -const urijs = require('uri-js') - -const base = 'uri://a/b/c/d;p?q' - -const domain = 'https://example.com/foo#bar$fiz' -const ipv4 = '//10.10.10.10' -const ipv6 = '//[2001:db8::7]' -const urn = 'urn:foo:a123,456' -const urnuuid = 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6' - -// Initialization as there is a lot to parse at first -// eg: regexes -fasturi.parse(domain) -urijs.parse(domain) - -suite.add('fast-uri: parse domain', function () { - fasturi.parse(domain) -}) -suite.add('urijs: parse domain', function () { - urijs.parse(domain) -}) -suite.add('WHATWG URL: parse domain', function () { - // eslint-disable-next-line - new URL(domain) -}) -suite.add('fast-uri: parse IPv4', function () { - fasturi.parse(ipv4) -}) -suite.add('urijs: parse IPv4', function () { - urijs.parse(ipv4) -}) -suite.add('fast-uri: parse IPv6', function () { - fasturi.parse(ipv6) -}) -suite.add('urijs: parse IPv6', function () { - urijs.parse(ipv6) -}) -suite.add('fast-uri: parse URN', function () { - fasturi.parse(urn) -}) -suite.add('urijs: parse URN', function () { - urijs.parse(urn) -}) -suite.add('WHATWG URL: parse URN', function () { - // eslint-disable-next-line - new URL(urn) -}) -suite.add('fast-uri: parse URN uuid', function () { - fasturi.parse(urnuuid) -}) -suite.add('urijs: parse URN uuid', function () { - urijs.parse(urnuuid) -}) -suite.add('fast-uri: serialize uri', function () { - fasturi.serialize({ - scheme: 'uri', - userinfo: 'foo:bar', - host: 'example.com', - port: 1, - path: 'path', - query: 'query', - fragment: 'fragment' - }) -}) -suite.add('urijs: serialize uri', function () { - urijs.serialize({ - scheme: 'uri', - userinfo: 'foo:bar', - host: 'example.com', - port: 1, - path: 'path', - query: 'query', - fragment: 'fragment' - }) -}) -suite.add('fast-uri: serialize long uri with dots', function () { - fasturi.serialize({ - scheme: 'uri', - userinfo: 'foo:bar', - host: 'example.com', - port: 1, - path: './a/./b/c/../.././d/../e/f/.././/', - query: 'query', - fragment: 'fragment' - }) -}) -suite.add('urijs: serialize long uri with dots', function () { - urijs.serialize({ - scheme: 'uri', - userinfo: 'foo:bar', - host: 'example.com', - port: 1, - path: './a/./b/c/../.././d/../e/f/.././/', - query: 'query', - fragment: 'fragment' - }) -}) -suite.add('fast-uri: serialize IPv6', function () { - fasturi.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }) -}) -suite.add('urijs: serialize IPv6', function () { - urijs.serialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }) -}) -suite.add('fast-uri: serialize ws', function () { - fasturi.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }) -}) -suite.add('urijs: serialize ws', function () { - urijs.serialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }) -}) -suite.add('fast-uri: resolve', function () { - fasturi.resolve(base, '../../../g') -}) -suite.add('urijs: resolve', function () { - urijs.resolve(base, '../../../g') -}) -suite.on('cycle', cycle) - -suite.run() - -function cycle (e) { - console.log(e.target.toString()) -} diff --git a/benchmark.mjs b/benchmark.mjs new file mode 100644 index 0000000..aa4dba5 --- /dev/null +++ b/benchmark.mjs @@ -0,0 +1,139 @@ +import { Bench } from 'tinybench' +import { fastUri } from './index.js' +import { parse as uriJsParse, serialize as uriJsSerialize, resolve as uriJsResolve } from 'uri-js' + +const base = 'uri://a/b/c/d;p?q' + +const domain = 'https://example.com/foo#bar$fiz' +const ipv4 = '//10.10.10.10' +const ipv6 = '//[2001:db8::7]' +const urn = 'urn:foo:a123,456' +const urnuuid = 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6' + +const { + parse: fastUriParse, + serialize: fastUriSerialize, + resolve: fastUriResolve +} = fastUri + +// Initialization as there is a lot to parse at first +// eg: regexes +fastUriParse(domain) +uriJsParse(domain) + +const benchFastUri = new Bench({ name: 'fast-uri benchmark' }) +const benchUriJs = new Bench({ name: 'uri-js benchmark' }) +const benchWHATWG = new Bench({ name: 'WHATWG URL benchmark' }) + +benchFastUri.add('fast-uri: parse domain', function () { + fastUriParse(domain) +}) +benchUriJs.add('urijs: parse domain', function () { + uriJsParse(domain) +}) +benchWHATWG.add('WHATWG URL: parse domain', function () { + // eslint-disable-next-line + new URL(domain) +}) +benchFastUri.add('fast-uri: parse IPv4', function () { + fastUriParse(ipv4) +}) +benchUriJs.add('urijs: parse IPv4', function () { + uriJsParse(ipv4) +}) +benchFastUri.add('fast-uri: parse IPv6', function () { + fastUriParse(ipv6) +}) +benchUriJs.add('urijs: parse IPv6', function () { + uriJsParse(ipv6) +}) +benchFastUri.add('fast-uri: parse URN', function () { + fastUriParse(urn) +}) +benchUriJs.add('urijs: parse URN', function () { + uriJsParse(urn) +}) +benchWHATWG.add('WHATWG URL: parse URN', function () { + // eslint-disable-next-line + new URL(urn) +}) +benchFastUri.add('fast-uri: parse URN uuid', function () { + fastUriParse(urnuuid) +}) +benchUriJs.add('urijs: parse URN uuid', function () { + uriJsParse(urnuuid) +}) +benchFastUri.add('fast-uri: serialize uri', function () { + fastUriSerialize({ + scheme: 'uri', + userinfo: 'foo:bar', + host: 'example.com', + port: 1, + path: 'path', + query: 'query', + fragment: 'fragment' + }) +}) +benchUriJs.add('urijs: serialize uri', function () { + uriJsSerialize({ + scheme: 'uri', + userinfo: 'foo:bar', + host: 'example.com', + port: 1, + path: 'path', + query: 'query', + fragment: 'fragment' + }) +}) +benchFastUri.add('fast-uri: serialize long uri with dots', function () { + fastUriSerialize({ + scheme: 'uri', + userinfo: 'foo:bar', + host: 'example.com', + port: 1, + path: './a/./b/c/../.././d/../e/f/.././/', + query: 'query', + fragment: 'fragment' + }) +}) +benchUriJs.add('urijs: serialize long uri with dots', function () { + uriJsSerialize({ + scheme: 'uri', + userinfo: 'foo:bar', + host: 'example.com', + port: 1, + path: './a/./b/c/../.././d/../e/f/.././/', + query: 'query', + fragment: 'fragment' + }) +}) +benchFastUri.add('fast-uri: serialize IPv6', function () { + fastUriSerialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }) +}) +benchUriJs.add('urijs: serialize IPv6', function () { + uriJsSerialize({ host: '2606:2800:220:1:248:1893:25c8:1946' }) +}) +benchFastUri.add('fast-uri: serialize ws', function () { + fastUriSerialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }) +}) +benchUriJs.add('urijs: serialize ws', function () { + uriJsSerialize({ scheme: 'ws', host: 'example.com', resourceName: '/foo?bar', secure: true }) +}) +benchFastUri.add('fast-uri: resolve', function () { + fastUriResolve(base, '../../../g') +}) +benchUriJs.add('urijs: resolve', function () { + uriJsResolve(base, '../../../g') +}) + +await benchFastUri.run() +console.log(benchFastUri.name) +console.table(benchFastUri.table()) + +await benchUriJs.run() +console.log(benchUriJs.name) +console.table(benchUriJs.table()) + +await benchWHATWG.run() +console.log(benchWHATWG.name) +console.table(benchWHATWG.table()) diff --git a/package.json b/package.json index e199d96..5895958 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ } ], "scripts": { - "bench": "node benchmark.js", + "bench": "node benchmark.mjs", "lint": "eslint", "lint:fix": "eslint --fix", "test": "npm run test:unit && npm run test:typescript", @@ -57,11 +57,11 @@ "devDependencies": { "@fastify/pre-commit": "^2.1.0", "ajv": "^8.16.0", - "benchmark": "^2.1.4", "coveralls": "^3.1.1", "eslint": "^9.17.0", "neostandard": "^0.12.0", "tape": "^5.8.1", + "tinybench": "^5.0.0", "tsd": "^0.32.0", "uri-js": "^4.4.1" } From 6af664706ccec562d1a138c94b5eb68bc51bc81d Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 16 Aug 2025 18:57:37 +0200 Subject: [PATCH 2/4] extract benchmark into own folder --- benchmark.mjs => benchmark/benchmark.mjs | 2 +- benchmark/package.json | 17 +++++++++++++++++ package.json | 1 - 3 files changed, 18 insertions(+), 2 deletions(-) rename benchmark.mjs => benchmark/benchmark.mjs (99%) create mode 100644 benchmark/package.json diff --git a/benchmark.mjs b/benchmark/benchmark.mjs similarity index 99% rename from benchmark.mjs rename to benchmark/benchmark.mjs index aa4dba5..0d992de 100644 --- a/benchmark.mjs +++ b/benchmark/benchmark.mjs @@ -1,5 +1,5 @@ import { Bench } from 'tinybench' -import { fastUri } from './index.js' +import { fastUri } from '../index.js' import { parse as uriJsParse, serialize as uriJsSerialize, resolve as uriJsResolve } from 'uri-js' const base = 'uri://a/b/c/d;p?q' diff --git a/benchmark/package.json b/benchmark/package.json new file mode 100644 index 0000000..7c0816a --- /dev/null +++ b/benchmark/package.json @@ -0,0 +1,17 @@ +{ + "name": "benchmark", + "version": "1.0.0", + "description": "", + "main": "index.js", + "private": true, + "scripts": { + "bench": "node benchmark.mjs" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "tinybench": "^5.0.0", + "uri-js": "^4.4.1" + } +} diff --git a/package.json b/package.json index 9231ad3..fd545e9 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "eslint": "^9.17.0", "neostandard": "^0.12.0", "tape": "^5.8.1", - "tinybench": "^5.0.0", "tsd": "^0.32.0" } } From 3c48839c1298f9814ba5afd437c36aca3054ba94 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 16 Aug 2025 19:15:50 +0200 Subject: [PATCH 3/4] remove benchmark npm script --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index fd545e9..40c4757 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ } ], "scripts": { - "bench": "node benchmark.mjs", "lint": "eslint", "lint:fix": "eslint --fix", "test": "npm run test:unit && npm run test:typescript", From ab105ecb187f7655a1642e0a6d9fadb40202f498 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Sat, 16 Aug 2025 19:40:19 +0200 Subject: [PATCH 4/4] update benchmarks --- README.md | 60 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index ff429ba..70984b8 100644 --- a/README.md +++ b/README.md @@ -94,29 +94,43 @@ fast-uri supports inserting custom [scheme](http://en.wikipedia.org/wiki/URI_sch ## Benchmarks ``` -fast-uri: parse domain x 1,306,864 ops/sec ±0.31% (100 runs sampled) -urijs: parse domain x 483,001 ops/sec ±0.09% (99 runs sampled) -WHATWG URL: parse domain x 862,461 ops/sec ±0.18% (97 runs sampled) -fast-uri: parse IPv4 x 2,381,452 ops/sec ±0.26% (96 runs sampled) -urijs: parse IPv4 x 384,705 ops/sec ±0.34% (99 runs sampled) -WHATWG URL: parse IPv4 NOT SUPPORTED -fast-uri: parse IPv6 x 923,519 ops/sec ±0.09% (100 runs sampled) -urijs: parse IPv6 x 289,070 ops/sec ±0.07% (95 runs sampled) -WHATWG URL: parse IPv6 NOT SUPPORTED -fast-uri: parse URN x 2,596,395 ops/sec ±0.42% (98 runs sampled) -urijs: parse URN x 1,152,412 ops/sec ±0.09% (97 runs sampled) -WHATWG URL: parse URN x 1,183,307 ops/sec ±0.38% (100 runs sampled) -fast-uri: parse URN uuid x 1,666,861 ops/sec ±0.10% (98 runs sampled) -urijs: parse URN uuid x 852,724 ops/sec ±0.17% (95 runs sampled) -WHATWG URL: parse URN uuid NOT SUPPORTED -fast-uri: serialize uri x 1,741,499 ops/sec ±0.57% (95 runs sampled) -urijs: serialize uri x 389,014 ops/sec ±0.28% (93 runs sampled) -fast-uri: serialize IPv6 x 441,095 ops/sec ±0.37% (97 runs sampled) -urijs: serialize IPv6 x 255,443 ops/sec ±0.58% (94 runs sampled) -fast-uri: serialize ws x 1,448,667 ops/sec ±0.25% (97 runs sampled) -urijs: serialize ws x 352,884 ops/sec ±0.08% (96 runs sampled) -fast-uri: resolve x 340,084 ops/sec ±0.98% (98 runs sampled) -urijs: resolve x 225,759 ops/sec ±0.37% (95 runs sampled) +fast-uri benchmark +┌─────────┬──────────────────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐ +│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │ +├─────────┼──────────────────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤ +│ 0 │ 'fast-uri: parse domain' │ '966.56 ± 0.76%' │ '888.00 ± 10.00' │ '1102014 ± 0.01%' │ '1126126 ± 12826' │ 1034600 │ +│ 1 │ 'fast-uri: parse IPv4' │ '697.95 ± 0.44%' │ '625.00 ± 8.00' │ '1562449 ± 0.01%' │ '1600000 ± 20221' │ 1432761 │ +│ 2 │ 'fast-uri: parse IPv6' │ '1319.9 ± 2.85%' │ '1180.0 ± 13.00' │ '834310 ± 0.02%' │ '847458 ± 9235' │ 757626 │ +│ 3 │ 'fast-uri: parse URN' │ '690.06 ± 0.23%' │ '636.00 ± 10.00' │ '1542937 ± 0.01%' │ '1572327 ± 25117' │ 1449157 │ +│ 4 │ 'fast-uri: parse URN uuid' │ '1047.2 ± 3.37%' │ '936.00 ± 18.00' │ '1050646 ± 0.02%' │ '1068376 ± 20158' │ 954915 │ +│ 5 │ 'fast-uri: serialize uri' │ '1138.6 ± 4.45%' │ '1005.0 ± 13.00' │ '973816 ± 0.02%' │ '995025 ± 12707' │ 878304 │ +│ 6 │ 'fast-uri: serialize long uri with dots' │ '1773.7 ± 0.36%' │ '1634.0 ± 14.00' │ '601087 ± 0.02%' │ '611995 ± 5289' │ 563798 │ +│ 7 │ 'fast-uri: serialize IPv6' │ '2532.7 ± 0.46%' │ '2334.0 ± 19.00' │ '421133 ± 0.03%' │ '428449 ± 3460' │ 394843 │ +│ 8 │ 'fast-uri: serialize ws' │ '1019.8 ± 2.06%' │ '926.00 ± 9.00' │ '1062555 ± 0.02%' │ '1079914 ± 10395' │ 980564 │ +│ 9 │ 'fast-uri: resolve' │ '2169.3 ± 0.49%' │ '1994.0 ± 21.00' │ '492756 ± 0.03%' │ '501505 ± 5338' │ 460987 │ +└─────────┴──────────────────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘ +uri-js benchmark +┌─────────┬───────────────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐ +│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │ +├─────────┼───────────────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤ +│ 0 │ 'urijs: parse domain' │ '3618.3 ± 0.43%' │ '3314.0 ± 33.00' │ '294875 ± 0.04%' │ '301750 ± 2975' │ 276375 │ +│ 1 │ 'urijs: parse IPv4' │ '4024.1 ± 0.41%' │ '3751.0 ± 25.00' │ '261981 ± 0.04%' │ '266596 ± 1789' │ 248506 │ +│ 2 │ 'urijs: parse IPv6' │ '5417.2 ± 0.46%' │ '4968.0 ± 43.00' │ '196023 ± 0.05%' │ '201288 ± 1727' │ 184598 │ +│ 3 │ 'urijs: parse URN' │ '1324.2 ± 0.23%' │ '1229.0 ± 17.00' │ '801535 ± 0.02%' │ '813670 ± 11413' │ 755185 │ +│ 4 │ 'urijs: parse URN uuid' │ '1822.0 ± 3.08%' │ '1655.0 ± 15.00' │ '594433 ± 0.02%' │ '604230 ± 5427' │ 548843 │ +│ 5 │ 'urijs: serialize uri' │ '4196.8 ± 0.36%' │ '3908.0 ± 27.00' │ '251146 ± 0.04%' │ '255885 ± 1756' │ 238276 │ +│ 6 │ 'urijs: serialize long uri with dots' │ '8331.0 ± 1.30%' │ '7658.0 ± 72.00' │ '126440 ± 0.07%' │ '130582 ± 1239' │ 120034 │ +│ 7 │ 'urijs: serialize IPv6' │ '5685.5 ± 0.30%' │ '5366.0 ± 33.00' │ '182632 ± 0.05%' │ '186359 ± 1153' │ 175886 │ +│ 8 │ 'urijs: serialize ws' │ '4159.3 ± 0.20%' │ '3899.0 ± 28.00' │ '250459 ± 0.04%' │ '256476 ± 1855' │ 240423 │ +│ 9 │ 'urijs: resolve' │ '6729.9 ± 0.39%' │ '6261.0 ± 37.00' │ '156361 ± 0.06%' │ '159719 ± 949' │ 148591 │ +└─────────┴───────────────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘ +WHATWG URL benchmark +┌─────────┬────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐ +│ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │ +├─────────┼────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤ +│ 0 │ 'WHATWG URL: parse domain' │ '475.22 ± 0.20%' │ '444.00 ± 5.00' │ '2217599 ± 0.01%' │ '2252252 ± 25652' │ 2104289 │ +│ 1 │ 'WHATWG URL: parse URN' │ '384.78 ± 0.85%' │ '350.00 ± 5.00' │ '2809071 ± 0.01%' │ '2857143 ± 41408' │ 2598885 │ +└─────────┴────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘ ``` ## TODO