Forge / Linux · 17–18 Oct 2026
Benchmarks
Stejná práce, stejný provoz. Prozkoumejte zaznamenaná měření, pochopte metodu a zopakujte každý test.
Total.js 4 0.0.99 · Express 5.3.0 · Fastify 5.12.7 · generator 8.0.0 · Meteor 3.5.2 · AdonisJS 6.21.0 · NestJS · Express 12.1.3 · Total.js 5 0.0.19
Porovnejte stejný scénář
RSS při zátěži · MiB
Sloupce ukazují medián ze tří opakování. Úsečky ukazují jejich minimum a maximum. Paměť je RSS procesu v MiB; každá osa začíná od nuly. Pořadí frameworků je pevné, není to žebříček.
| Framework | Výchozí RSS · MiB | RSS při zátěži · MiB | RSS po zátěži · MiB | CPU · % | Latence p99 · ms | Pokrytí cíle · % | Zdravé běhy |
|---|---|---|---|---|---|---|---|
| Total.js 4 | 61.0 [60.9–61.1] | 159.3 [150.1–167.0] | 174.3 [172.9–174.5] | 7.9 [7.8–8.2] | 5.0 [5.0–5.0] | 100.0 [100.0–100.0] | 3/3 |
| Total.js 5 | 62.8 [62.8–63.2] | 165.7 [164.9–166.7] | 173.8 [173.1–174.3] | 8.2 [8.1–8.2] | 6.0 [6.0–6.0] | 100.0 [100.0–100.0] | 3/3 |
| Express | 74.1 [73.9–74.2] | 90.8 [90.4–91.5] | 90.9 [90.5–91.6] | 7.3 [7.1–7.6] | 5.0 [4.0–5.0] | 100.0 [100.0–100.0] | 3/3 |
| Fastify | 75.9 [75.4–76.8] | 91.2 [91.0–91.6] | 91.2 [91.0–91.6] | 4.9 [4.9–5.0] | 3.0 [3.0–3.0] | 100.0 [100.0–100.0] | 3/3 |
| Node.js http | 50.2 [50.2–50.2] | 67.9 [67.5–69.8] | 67.9 [67.7–70.0] | 4.4 [4.4–4.5] | 3.0 [3.0–3.0] | 100.0 [100.0–100.0] | 3/3 |
| Meteor | 124.3 [123.4–125.5] | 168.6 [167.6–171.1] | 169.0 [168.5–172.3] | 12.8 [12.7–12.8] | 10.0 [8.0–18.0] | 100.0 [100.0–100.0] | 3/3 |
| AdonisJS | 114.3 [113.6–115.4] | 145.3 [144.6–149.7] | 145.3 [144.6–149.6] | 10.7 [10.4–10.7] | 6.0 [6.0–7.0] | 100.0 [100.0–100.0] | 3/3 |
| NestJS · Express | 100.4 [99.3–101.3] | 129.6 [129.4–130.0] | 129.8 [129.4–130.2] | 8.5 [8.5–8.6] | 5.0 [5.0–13.0] | 100.0 [100.0–100.0] | 3/3 |
Node.jsTotal.js 4 · v24.14.1 Total.js 5 · v24.15.0 Express · v24.14.1 Fastify · v24.14.1 Node.js http · v24.14.1 Meteor · v24.15.0 AdonisJS · v24.15.0 NestJS · Express · v24.15.0 | |||||||
Hodnoty jsou medián [minimum–maximum] z opakování. Každá hodnota RSS je medián v rámci fáze; vzorkované špičky zůstávají v surových datech. Výchozí hodnota následuje po kontrolních požadavcích, takže není pamětí zcela bez požadavků. CPU je procento jednoho logického CPU ve vzorkovaném okně. p99 popisuje dokončené požadavky; čtěte jej spolu s chybami a pokrytím cíle.
Paměť během jednoho měření
Jeden nový proces, vzorkovaný každou sekundu. Zvýrazněná okna označují zátěž a zotavení; před zátěží probíhá zahřívání a ustálení. RSS zahrnuje runtime, heap a nativní paměť. Není to živý heap JavaScriptu.
Stáhnout kit a připravit počítač
Spustit po přípravě testovacího kitu
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/run.cjs --frameworks totaljs --workloads hello --rates 1000 --seconds 60 --warmup 15 --rest 30 --reps 3 --connections 32 --out /results/my-run.jsonPříkaz používá zmrazenou sadu zvoleného běhu. Před porovnáním opakování sjednoťte hardware, limity kontejneru a aktivitu na pozadí. Po dokončení ověřte příslušným v2/verify.cjs.
Jak číst výsledek
Porovnávejte stejnou zátěž při stejném cílovém tempu a čtěte spolu latenci, CPU, paměť, chyby a pokrytí cíle. Záleží i na verzi runtime. Tato měření nedokazují, že jeden framework vždy spotřebuje méně zdrojů. Total.js 4 a 5 jsou uvedeny zvlášť; každý používá svou zaznamenanou implementaci a runtime.
Co se měřilo
Osm adaptérů, čtyři zátěže a společné cíle 100 a 1 000 požadavků/s: 192 měření. Každé měření spouští nový produkční proces: kontrola odpovědi, 1,5 s základ, 15 s zahřívání, 6 s ustálení, 60 s zátěže a 30 s zotavení. Zachována jsou všechna tři opakování. Adaptéry se měřily postupně. Obsah úspěšných odpovědí se kontroluje před zátěží i po ní; generátor žádá až 32 spojení.
Total5 používá kompaktní NEWSCHEMA a přímý controller k validaci JSON; malé odpovědi JSON vrací přímo controller. Srovnání obsahuje úplné zaznamenané scénáře, nikdy nejlepší číselný výsledek. Meteor používá svůj produkční bundle jen pro server; NestJS svůj adaptér Express. Nativní validátory pokrývají měřený obsah; odmítání a konverze se mohou mezi frameworky lišit.
Prostředí
Sdílený server Linux x64, Intel Core i7-6700. Každý měřicí kontejner byl omezen na 2 logické CPU a 2 GiB, bez vnější sítě a publikovaných portů. Generátor a simulovaná závislost sdílely kontejner. Node 24.14.1 byl použit pro Total4, Express, Fastify a Node http; Node 24.15.0 pro Total5, Meteor, AdonisJS a NestJS, v souladu s runtime bundlu Meteoru. Verze runtime jsou uvedeny u každého frameworku: rozdíly nelze přičítat pouze frameworku. Produkční služby zůstaly na serveru.
Co tyto výsledky nedokazují
Jde o experiment s pevným tempem a uzavřenou smyčkou, nikoli o žebříček maximální propustnosti. Dosažení nastaveného cíle nedokazuje, jak adaptér zvládá nezávislé příchody nebo nasycení. Došlo k určitému omezování CPU kvótou, zaznamenanému v revizi. Tři krátká opakování nedokazují dlouhodobou stabilitu, absenci úniků paměti, produkční bezpečnost, chování Flow ani využití paměti na Raspberry Pi. Sběr odpadu nebyl vynucen. RSS může zůstat alokováno i po skončení provozu.
Buňka je zdravá, když dokončené požadavky dosáhnou alespoň 95 % cíle × doba generátoru, p99 nepřesáhne 250 ms a počty chyb, timeoutů a odpovědí mimo 2xx jsou nulové. Tento práh netvrdí, že všechny mají stejnou maximální kapacitu.
Původní důkazy
Revize integrity a prostředí · Kontrolní součty SHA-256 · JSON · Markdown
Reprodukovat a ověřit
Použijte prázdný adresář s Dockerem (kontejnery Linux), curl a tar. Node.js na hostiteli nepotřebujete: kontrola kontrolního součtu i testy používají Node 24.15.0 v Dockeru. První sestavení stahuje závislosti a kompiluje Meteor, což může trvat několik minut. Příprava vyžaduje internet; testovací kontejnery nemají vnější síť. Každý měřený scénář trvá zhruba šest minut.
Kit spouští všech osm adaptérů na Node v24.15.0. Publikovaná měření si zachovávají původní runtime, uvedené v tabulce.
Stáhnout kompletní testovací kit
1. Stáhnout a připravit. Odkaz obsahuje spouštěč, adaptéry a zámky závislostí; není třeba instalovat Forge ani klonovat repozitář. V prázdném adresáři spusťte následující příkazy. Pokud jste stáhli tlačítkem, ponechte název sources.tar.gz a vynechte curl.
curl --fail --location --output sources.tar.gz 'https://forge.totaljs.es/benchmarks/node-24.15.0/sources.tar.gz' &&
docker run --rm --platform linux/amd64 --network none -v "$PWD:/kit:ro" node:24.15.0-bookworm node -e 'const fs=require("node:fs"),crypto=require("node:crypto");if(crypto.createHash("sha256").update(fs.readFileSync("/kit/sources.tar.gz")).digest("hex")!=="65801cd865a3fc961e69ba8df421ed198acdc399d29934714fb954e4de1db651")throw Error("SHA-256 mismatch");' &&
tar -xzf sources.tar.gz &&
docker build --platform linux/amd64 -t forge-benchmark-local . &&
mkdir -p results
2. Zkontrolovat instalaci (asi 15–30 sekund). Tento krátký test vytvoří smoke.json a ověří jeho zaznamenané vstupy; není to publikovatelný výkonnostní výsledek.
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/run.cjs --smoke --frameworks totaljs --workloads hello --rates 1000 --out /results/smoke.json
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/verify.cjs /results/smoke.json --allow-smoke
3. Spustit a ověřit zvolené měření. Výsledky se uloží do results/my-run.json ve zvoleném adresáři benchmarks. Spouštěč odmítá přepsat existující výstup: při opakování použijte jiný název souboru. Ověření kontroluje úplnost a vstupy, ne shodu s publikovanými hodnotami.
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/run.cjs --frameworks totaljs --workloads hello --rates 1000 --seconds 60 --warmup 15 --rest 30 --reps 3 --connections 32 --out /results/my-run.json
docker run --rm --platform linux/amd64 --cpus 2 --memory 2g --memory-swap 2g --pids-limit 256 --read-only --network none --user "$(id -u):$(id -g)" --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 -v "$PWD/results:/results" forge-benchmark-local node benchmarks/v2/verify.cjs /results/my-run.json