From 338aead31e62c22c80d7b62b08e7510d7096a672 Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Fri, 6 Nov 2026 07:10:46 +0100 Subject: [PATCH 1/2] fulmine.js - uwsLite: new entry on the scored H/1.1 profiles --- frameworks/fulmine-uwslite/Dockerfile | 19 +++++++ frameworks/fulmine-uwslite/README.md | 17 ++++++ frameworks/fulmine-uwslite/app.js | 73 +++++++++++++++++++++++++ frameworks/fulmine-uwslite/meta.json | 28 ++++++++++ frameworks/fulmine-uwslite/package.json | 7 +++ 5 files changed, 144 insertions(+) create mode 100644 frameworks/fulmine-uwslite/Dockerfile create mode 100644 frameworks/fulmine-uwslite/README.md create mode 100644 frameworks/fulmine-uwslite/app.js create mode 100644 frameworks/fulmine-uwslite/meta.json create mode 100644 frameworks/fulmine-uwslite/package.json diff --git a/frameworks/fulmine-uwslite/Dockerfile b/frameworks/fulmine-uwslite/Dockerfile new file mode 100644 index 0000000000..af515de3a8 --- /dev/null +++ b/frameworks/fulmine-uwslite/Dockerfile @@ -0,0 +1,19 @@ +FROM node:26-trixie-slim AS build +RUN apt-get update && \ + apt-get install -y --no-install-recommends ca-certificates git && \ + rm -rf /var/lib/apt/lists/* +RUN git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" +WORKDIR /app +COPY package.json . +RUN npm install --omit=dev + +FROM node:26-trixie-slim +RUN apt-get update && \ + apt-get install -y --no-install-recommends ca-certificates curl && \ + rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY --from=build /app/node_modules ./node_modules +COPY app.js . +ENV NODE_ENV=production +EXPOSE 8080 +CMD ["node", "app.js"] diff --git a/frameworks/fulmine-uwslite/README.md b/frameworks/fulmine-uwslite/README.md new file mode 100644 index 0000000000..ad1b82c63a --- /dev/null +++ b/frameworks/fulmine-uwslite/README.md @@ -0,0 +1,17 @@ +# fulmine.js - uwsLite + +fulmine.js with its routes written with `app.uwsLite`: `(req, res)` handlers that uWebSockets.js serves over two small objects, with no Express layer in front. It runs only the H/1.1 profiles that count for the score. + +## Stack + +- **Language:** JavaScript +- **Runtime:** Node.js 26 +- **Framework:** [fulmine.js](https://github.com/nigrosimone/fulmine.js) +- **Build:** multi-stage, `node:26-trixie-slim` for both stages + +## Endpoints + +- `GET` and `POST /baseline11`: the sum of the query, and of the body +- `GET /delay/:ms`: answers after the wait +- `GET /json/:count?m=`: the dataset, compressed with brotli when asked +- `GET /json/:count` and `POST /echo` over TLS on 8081 diff --git a/frameworks/fulmine-uwslite/app.js b/frameworks/fulmine-uwslite/app.js new file mode 100644 index 0000000000..6ff7687e41 --- /dev/null +++ b/frameworks/fulmine-uwslite/app.js @@ -0,0 +1,73 @@ +// fulmine.js with app.uwsLite: an (req, res) route that uWS serves over two small objects. +// https://fulmine.sndesign.it/uws-routes#lite-routes-app-uwslite +const fs = require('fs'); +const zlib = require('zlib'); +const express = require('fulmine.js'); + +// One worker per usable core (cgroup quota first), all on the same port with SO_REUSEPORT. +// https://fulmine.sndesign.it/examples/cluster +const app = express({ cluster: 'auto' }); + +const dataset = JSON.parse(fs.readFileSync('/data/dataset.json', 'utf8')); + +// Brotli quality 3, as the fulmine entry. +const compress = { + encodings: ['br'], + brotli: { params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 3 } }, +}; + +function sumQuery(query) { + let sum = 0; + for (const k in query) { + const n = parseInt(query[k], 10); + if (n === n) sum += n; + } + return sum; +} + +app.uwsLite.get('/baseline11', (req, res) => { + res.type('text/plain').send(String(sumQuery(req.query))); +}); + +app.uwsLite.post('/baseline11', { body: 'text' }, (req, res) => { + let total = sumQuery(req.query); + const n = parseInt(req.body.trim(), 10); + if (n === n) total += n; + res.type('text/plain').send(String(total)); +}); + +app.uwsLite.get('/delay/:ms', (req, res) => { + const ms = parseInt(req.params.ms, 10) || 0; + setTimeout(() => res.type('text/plain').send(String(ms)), ms); +}); + +const json = (req, res) => { + const count = Math.min(Math.max(parseInt(req.params.count, 10) || 0, 0), dataset.length); + const m = parseInt(req.query.m, 10) || 1; + const items = new Array(count); + for (let i = 0; i < count; i++) { + const d = dataset[i]; + items[i] = { + id: d.id, name: d.name, category: d.category, + price: d.price, quantity: d.quantity, active: d.active, + tags: d.tags, rating: d.rating, + total: d.price * d.quantity * m + }; + } + res.json({ items, count }); +}; + +app.uwsLite.get('/json/:count', { compress }, json); + +// json-tls and 8gbit over TLS on 8081, when the harness mounts the certs. json-tls never sends +// Accept-Encoding, so this route has no compress. The echo answers while the body is lent. +if (fs.existsSync('/certs/server.key') && fs.existsSync('/certs/server.crt')) { + const tls = express({ uwsOptions: { key_file_name: '/certs/server.key', cert_file_name: '/certs/server.crt' } }); + tls.uwsLite.get('/json/:count', json); + tls.uwsLite.post('/echo', { body: 'lent', limit: '1mb' }, (req, res) => { + res.type('application/octet-stream').send(req.body); + }); + tls.listen(8081); +} + +app.listen(8080); diff --git a/frameworks/fulmine-uwslite/meta.json b/frameworks/fulmine-uwslite/meta.json new file mode 100644 index 0000000000..c3fdc9baba --- /dev/null +++ b/frameworks/fulmine-uwslite/meta.json @@ -0,0 +1,28 @@ +{ + "display_name": "fulmine.js - uwsLite", + "language": "JS", + "type": "emerging", + "mode": "standard", + "completeness": { + "routing": true, + "middleware": true, + "request": true, + "response": true + }, + "engine": "uwebsockets", + "description": "fulmine.js routes written with app.uwsLite: (req, res) handlers on uWebSockets.js over two small objects, with route middleware and streams.", + "repo": "https://github.com/nigrosimone/fulmine.js", + "website": "https://fulmine.sndesign.it/", + "enabled": true, + "tests": [ + "baseline", + "limited-conn", + "async", + "latency-10k", + "latency-1m", + "json-comp", + "json-tls", + "8gbit" + ], + "maintainers": ["nigrosimone"] +} diff --git a/frameworks/fulmine-uwslite/package.json b/frameworks/fulmine-uwslite/package.json new file mode 100644 index 0000000000..501f2bd845 --- /dev/null +++ b/frameworks/fulmine-uwslite/package.json @@ -0,0 +1,7 @@ +{ + "name": "httparena-fulmine-uwslite", + "private": true, + "dependencies": { + "fulmine.js": "^5.31.0" + } +} From 477676712a06d436159da307958a8d29c7dfc319 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Nov 2026 08:22:13 +0000 Subject: [PATCH 2/2] Benchmark results: fulmine-uwslite [skip ci] --- site/data/frameworks.json | 15 ++ site/data/results/fulmine.js---uwslite.json | 197 ++++++++++++++++++ .../static/logs/8gbit/512/fulmine-uwslite.log | 0 .../logs/async/32000/fulmine-uwslite.log | 0 .../logs/baseline/4096/fulmine-uwslite.log | 0 .../logs/json-comp/16384/fulmine-uwslite.log | 0 .../logs/json-comp/4096/fulmine-uwslite.log | 0 .../logs/json-tls/4096/fulmine-uwslite.log | 0 .../logs/latency-10k/1024/fulmine-uwslite.log | 0 .../logs/latency-1m/1024/fulmine-uwslite.log | 0 .../limited-conn/4096/fulmine-uwslite.log | 0 11 files changed, 212 insertions(+) create mode 100644 site/data/results/fulmine.js---uwslite.json create mode 100644 site/static/logs/8gbit/512/fulmine-uwslite.log create mode 100644 site/static/logs/async/32000/fulmine-uwslite.log create mode 100644 site/static/logs/baseline/4096/fulmine-uwslite.log create mode 100644 site/static/logs/json-comp/16384/fulmine-uwslite.log create mode 100644 site/static/logs/json-comp/4096/fulmine-uwslite.log create mode 100644 site/static/logs/json-tls/4096/fulmine-uwslite.log create mode 100644 site/static/logs/latency-10k/1024/fulmine-uwslite.log create mode 100644 site/static/logs/latency-1m/1024/fulmine-uwslite.log create mode 100644 site/static/logs/limited-conn/4096/fulmine-uwslite.log diff --git a/site/data/frameworks.json b/site/data/frameworks.json index 57f98c2eab..7e0e3376e1 100644 --- a/site/data/frameworks.json +++ b/site/data/frameworks.json @@ -834,6 +834,21 @@ "response": false } }, + "fulmine.js - uwsLite": { + "dir": "fulmine-uwslite", + "description": "fulmine.js routes written with app.uwsLite: (req, res) handlers on uWebSockets.js over two small objects, with route middleware and streams.", + "repo": "https://github.com/nigrosimone/fulmine.js", + "type": "emerging", + "engine": "uwebsockets", + "mode": "standard", + "website": "https://fulmine.sndesign.it/", + "completeness": { + "routing": true, + "middleware": true, + "request": true, + "response": true + } + }, "fulmine.js": { "dir": "fulmine", "description": "fulmine.js (drop-in Express 5 on uWebSockets.js) with its own cluster option for multi-core scaling.", diff --git a/site/data/results/fulmine.js---uwslite.json b/site/data/results/fulmine.js---uwslite.json new file mode 100644 index 0000000000..5bf85d550c --- /dev/null +++ b/site/data/results/fulmine.js---uwslite.json @@ -0,0 +1,197 @@ +{ + "framework": "fulmine.js - uwsLite", + "results": { + "8gbit-512": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 49342, + "avg_latency": "92.2us", + "p99_latency": "120.0us", + "cpu": "216.5%", + "memory": "1.2GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "511.13MB/s", + "input_bw": "481.86MB/s", + "reconnects": 0, + "status_2xx": 246774, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 11950026, + "cpu_per_req_us": 48.425, + "target_rate": 50000, + "rate_ratio": 0.9868, + "p99_9_latency": "3539.0us" + }, + "async-32000": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 2458459, + "avg_latency": "12.92ms", + "p99_latency": "16.10ms", + "cpu": "5802.7%", + "memory": "3.5GiB", + "connections": 32000, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "276.61MB/s", + "input_bw": "112.54MB/s", + "reconnects": 0, + "status_2xx": 24584597, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-4096": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 2711810, + "avg_latency": "1.51ms", + "p99_latency": "2.90ms", + "cpu": "6681.9%", + "memory": "1.7GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "305.07MB/s", + "input_bw": "209.48MB/s", + "reconnects": 0, + "status_2xx": 13559054, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-comp-16384": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 476174, + "avg_latency": "34.09ms", + "p99_latency": "79.80ms", + "cpu": "6244.9%", + "memory": "2.3GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "635.10MB/s", + "input_bw": "35.42MB/s", + "reconnects": 87069, + "status_2xx": 2380870, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-comp-4096": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 478865, + "avg_latency": "8.54ms", + "p99_latency": "24.30ms", + "cpu": "6318.8%", + "memory": "2.1GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "638.69MB/s", + "input_bw": "35.62MB/s", + "reconnects": 94151, + "status_2xx": 2394325, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-tls-4096": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 1388473, + "avg_latency": "2.92ms", + "p99_latency": "58.69ms", + "cpu": "6392.9%", + "memory": "1.7GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.71GB", + "reconnects": 0, + "status_2xx": 7080611, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "latency-10k-1024": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 9983, + "avg_latency": "74.3us", + "p99_latency": "108.0us", + "cpu": "30.7%", + "memory": "1.3GiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "1.17MB/s", + "reconnects": 0, + "status_2xx": 199679, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 6391614, + "cpu_per_req_us": 32.0094, + "target_rate": 10000, + "rate_ratio": 0.9983, + "p99_9_latency": "186.0us" + }, + "latency-1m-1024": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 998128, + "avg_latency": "109.8us", + "p99_latency": "197.0us", + "cpu": "2918.9%", + "memory": "1.5GiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "116.78MB/s", + "reconnects": 0, + "status_2xx": 19966012, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 529359256, + "cpu_per_req_us": 26.513, + "target_rate": 1000000, + "rate_ratio": 0.9981, + "p99_9_latency": "4186.0us" + }, + "limited-conn-4096": { + "framework": "fulmine.js - uwsLite", + "language": "JS", + "rps": 2318031, + "avg_latency": "1.74ms", + "p99_latency": "6.44ms", + "cpu": "6463.1%", + "memory": "1.6GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "260.76MB/s", + "input_bw": "179.06MB/s", + "reconnects": 1158239, + "status_2xx": 11590156, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + } + } +} diff --git a/site/static/logs/8gbit/512/fulmine-uwslite.log b/site/static/logs/8gbit/512/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/async/32000/fulmine-uwslite.log b/site/static/logs/async/32000/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/baseline/4096/fulmine-uwslite.log b/site/static/logs/baseline/4096/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/json-comp/16384/fulmine-uwslite.log b/site/static/logs/json-comp/16384/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/json-comp/4096/fulmine-uwslite.log b/site/static/logs/json-comp/4096/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/json-tls/4096/fulmine-uwslite.log b/site/static/logs/json-tls/4096/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/latency-10k/1024/fulmine-uwslite.log b/site/static/logs/latency-10k/1024/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/latency-1m/1024/fulmine-uwslite.log b/site/static/logs/latency-1m/1024/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/site/static/logs/limited-conn/4096/fulmine-uwslite.log b/site/static/logs/limited-conn/4096/fulmine-uwslite.log new file mode 100644 index 0000000000..e69de29bb2