# Benchmarks

Rovnaká práca, rovnaká záťaž. Preskúmajte zaznamenané merania, spoznajte metódu a zopakujte každý test.

## Čo sa meralo

Osem adaptérov, štyri záťaže a spoločné ciele 100 a 1 000 požiadaviek/s: 192 meraní. Každé meranie spúšťa nový produkčný proces: kontrola odpovede, 1,5 s východisko, 15 s zahrievanie, 6 s ustálenie, 60 s záťaž a 30 s zotavenie. Zachované sú všetky tri opakovania. Adaptéry sa merali postupne. Telá úspešných odpovedí sa kontrolujú pred záťažou aj po nej; generátor žiada až 32 spojení.

Total5 používa kompaktné NEWSCHEMA a priamy controller na validáciu JSON; malé odpovede JSON vracia priamo controller. Porovnanie obsahuje úplné zaznamenané scenáre, nikdy nie najlepší číselný výsledok. Meteor používa svoj produkčný bundle iba pre server; NestJS používa adaptér Express. Natívne validátory pokrývajú meraný obsah; odmietanie a konverzie sa môžu medzi frameworkmi líšiť.

## Prostredie

Zdieľaný server Linux x64, Intel Core i7-6700. Každý kontajner merania bol obmedzený na 2 logické CPU a 2 GiB, bez vonkajšej siete a bez publikovaných portov. Generátor a simulovaná závislosť zdieľali kontajner. Node 24.14.1 sa použil pre Total4, Express, Fastify a Node http; Node 24.15.0 pre Total5, Meteor, AdonisJS a NestJS, v súlade s runtime bundlu Meteoru. Verzie runtime sú uvedené pri každom frameworku: rozdiely nemožno pripísať iba frameworku. Produkčné služby zostali na serveri.

## Čo tieto výsledky nedokazujú

Ide o experiment s pevnou záťažou a uzavretou slučkou, nie o rebríček maximálnej priepustnosti. Dosiahnutie nastaveného cieľa nedokazuje, ako adaptér zvláda nezávislé príchody alebo nasýtenie. Došlo k určitému obmedzovaniu CPU kvótou, zaznamenanému v revízii. Tri krátke opakovania nedokazujú dlhodobú stabilitu, absenciu únikov pamäte, bezpečnosť v produkcii, správanie Flow ani využitie pamäte na Raspberry Pi. Nevynucovalo sa zber odpadu. RSS môže zostať alokované aj po skončení záťaže.

Bunka je zdravá, keď dokončené požiadavky dosiahnu aspoň 95 % cieľa × trvanie generátora, p99 nie je vyššie ako 250 ms a počty chýb, timeoutov a odpovedí mimo 2xx sú nulové. Tento prah netvrdí, že všetky majú rovnakú maximálnu kapacitu.

## Ako čítať výsledok

Porovnávajte tú istú záťaž pri rovnakom cieľovom tempe a čítajte spolu latenciu, CPU, pamäť, chyby a pokrytie cieľa. Dôležitá je aj verzia runtime. Tieto merania nedokazujú, že jeden framework vždy spotrebuje menej zdrojov. Total.js 4 a 5 sú uvedené samostatne; každý používa svoju zaznamenanú implementáciu a runtime.

## Kompletné porovnanie frameworkov

Dokončené: 2026-10-18T13:56:39.143Z; Node v24.14.1 / v24.15.0 (see runtimeByFramework).

| Framework | Node | Workload | req/s | Healthy | RSS baseline MiB | RSS load MiB | RSS recovery MiB | CPU % | p99 ms |
|---|---|---|---:|---|---|---|---|---|---|
| Total.js 4 | v24.14.1 | hello | 100 | 3/3 | 61.2 [61.0–61.2] | 89.8 [87.0–90.7] | 91.0 [88.3–105.4] | 1.7 [1.7–1.7] | 5.0 [5.0–6.0] |
| Express | v24.14.1 | hello | 100 | 3/3 | 74.2 [74.1–74.3] | 90.7 [90.4–91.5] | 90.8 [90.3–91.5] | 1.9 [1.9–2.0] | 7.0 [6.0–7.0] |
| Fastify | v24.14.1 | hello | 100 | 3/3 | 76.0 [75.5–76.0] | 91.3 [91.0–91.9] | 91.4 [91.0–91.9] | 1.4 [1.4–1.4] | 5.0 [5.0–5.0] |
| Node.js http | v24.14.1 | hello | 100 | 3/3 | 50.2 [50.2–50.3] | 68.8 [66.6–69.2] | 69.2 [67.0–69.5] | 1.4 [1.4–1.4] | 5.0 [5.0–5.0] |
| Total.js 4 | v24.14.1 | catalog | 100 | 3/3 | 61.3 [61.1–62.1] | 104.6 [94.9–106.2] | 106.4 [105.1–108.6] | 2.1 [2.1–2.1] | 8.0 [8.0–8.0] |
| Express | v24.14.1 | catalog | 100 | 3/3 | 74.1 [74.0–74.1] | 92.0 [91.9–94.5] | 92.3 [91.9–94.5] | 2.3 [2.3–2.4] | 9.0 [9.0–9.0] |
| Fastify | v24.14.1 | catalog | 100 | 3/3 | 75.8 [75.2–75.8] | 93.2 [92.6–93.4] | 93.4 [93.1–93.5] | 1.9 [1.8–1.9] | 8.0 [7.0–8.0] |
| Node.js http | v24.14.1 | catalog | 100 | 3/3 | 50.2 [50.1–50.3] | 66.0 [65.9–68.4] | 66.3 [66.1–68.7] | 1.8 [1.8–1.8] | 6.0 [6.0–7.0] |
| Total.js 4 | v24.14.1 | validate | 100 | 3/3 | 61.4 [61.3–61.6] | 96.4 [95.4–100.2] | 100.8 [98.3–101.9] | 2.0 [2.0–2.2] | 7.0 [6.0–8.0] |
| Express | v24.14.1 | validate | 100 | 3/3 | 74.0 [74.0–75.0] | 98.5 [94.4–99.0] | 98.6 [94.4–99.3] | 2.3 [2.2–2.3] | 9.0 [8.0–9.0] |
| Fastify | v24.14.1 | validate | 100 | 3/3 | 75.7 [75.6–76.0] | 97.3 [96.6–98.0] | 97.7 [96.2–98.0] | 1.7 [1.6–1.7] | 6.0 [5.0–6.0] |
| Node.js http | v24.14.1 | validate | 100 | 3/3 | 50.3 [50.2–50.5] | 71.6 [71.4–72.2] | 71.8 [71.4–72.6] | 1.7 [1.7–1.7] | 6.0 [6.0–6.0] |
| Total.js 4 | v24.14.1 | upstream | 100 | 3/3 | 67.2 [66.8–67.9] | 167.8 [166.7–169.5] | 175.3 [169.6–176.7] | 5.7 [5.7–5.8] | 19.0 [19.0–19.0] |
| Express | v24.14.1 | upstream | 100 | 3/3 | 80.2 [79.8–80.2] | 171.3 [171.2–171.4] | 173.7 [172.9–173.7] | 6.0 [5.7–6.2] | 20.0 [19.0–20.0] |
| Fastify | v24.14.1 | upstream | 100 | 3/3 | 80.3 [80.1–80.7] | 165.9 [165.8–168.4] | 168.7 [168.3–173.1] | 5.6 [4.8–5.8] | 20.0 [19.0–20.0] |
| Node.js http | v24.14.1 | upstream | 100 | 3/3 | 60.8 [60.7–61.6] | 161.9 [158.4–172.1] | 164.2 [159.9–174.2] | 5.5 [5.2–5.5] | 18.0 [18.0–19.0] |
| Total.js 4 | v24.14.1 | hello | 1000 | 3/3 | 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] |
| Express | v24.14.1 | hello | 1000 | 3/3 | 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] |
| Fastify | v24.14.1 | hello | 1000 | 3/3 | 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] |
| Node.js http | v24.14.1 | hello | 1000 | 3/3 | 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] |
| Total.js 4 | v24.14.1 | catalog | 1000 | 3/3 | 61.2 [61.0–61.3] | 179.5 [179.5–180.0] | 179.9 [179.4–180.2] | 9.9 [9.9–9.9] | 13.0 [6.0–18.0] |
| Express | v24.14.1 | catalog | 1000 | 3/3 | 73.8 [73.7–74.0] | 91.8 [91.1–92.9] | 91.8 [91.3–92.9] | 9.5 [9.4–9.8] | 5.0 [5.0–11.0] |
| Fastify | v24.14.1 | catalog | 1000 | 3/3 | 75.7 [75.3–75.9] | 94.1 [93.8–94.2] | 94.1 [93.8–94.2] | 7.1 [7.1–7.1] | 5.0 [5.0–5.0] |
| Node.js http | v24.14.1 | catalog | 1000 | 3/3 | 50.2 [50.1–50.2] | 72.6 [71.2–72.9] | 72.6 [71.2–73.2] | 7.3 [7.2–7.4] | 5.0 [4.0–5.0] |
| Total.js 4 | v24.14.1 | validate | 1000 | 3/3 | 62.2 [61.6–62.5] | 171.9 [170.7–172.7] | 175.7 [175.3–176.6] | 9.7 [9.5–10.0] | 6.0 [6.0–6.0] |
| Express | v24.14.1 | validate | 1000 | 3/3 | 74.4 [74.2–74.6] | 98.8 [98.2–99.7] | 98.8 [98.2–99.7] | 8.9 [8.9–9.2] | 8.0 [6.0–21.0] |
| Fastify | v24.14.1 | validate | 1000 | 3/3 | 75.9 [75.7–76.4] | 98.1 [98.1–98.4] | 98.1 [98.1–98.5] | 6.3 [6.2–6.3] | 5.0 [4.0–12.0] |
| Node.js http | v24.14.1 | validate | 1000 | 3/3 | 50.2 [50.2–50.4] | 71.0 [70.4–72.6] | 74.9 [74.2–76.4] | 6.2 [6.0–6.3] | 4.0 [4.0–13.0] |
| Total.js 4 | v24.14.1 | upstream | 1000 | 3/3 | 67.8 [67.8–67.8] | 202.3 [201.4–204.1] | 203.0 [201.6–204.7] | 36.3 [34.7–36.6] | 16.0 [15.0–16.0] |
| Express | v24.14.1 | upstream | 1000 | 3/3 | 80.7 [79.7–80.9] | 178.7 [177.6–187.7] | 182.6 [181.9–190.4] | 35.0 [32.6–35.4] | 15.0 [15.0–16.0] |
| Fastify | v24.14.1 | upstream | 1000 | 3/3 | 79.3 [79.3–79.3] | 194.0 [179.4–194.6] | 194.0 [179.6–194.9] | 33.8 [27.7–34.2] | 15.0 [14.0–15.0] |
| Node.js http | v24.14.1 | upstream | 1000 | 3/3 | 60.9 [60.7–61.0] | 171.9 [171.8–174.6] | 178.0 [175.5–179.3] | 29.0 [23.6–30.5] | 14.0 [13.0–15.0] |
| Meteor | v24.15.0 | hello | 100 | 3/3 | 123.7 [123.5–124.7] | 130.2 [128.1–131.3] | 159.1 [151.6–160.9] | 3.5 [3.5–3.6] | 15.0 [14.0–19.0] |
| Meteor | v24.15.0 | catalog | 100 | 3/3 | 124.7 [123.3–124.8] | 138.9 [138.8–139.4] | 162.5 [157.0–162.7] | 3.9 [3.9–4.0] | 15.0 [14.0–16.0] |
| Meteor | v24.15.0 | validate | 100 | 3/3 | 124.4 [123.2–124.6] | 137.0 [134.6–138.8] | 163.4 [161.2–169.2] | 3.9 [3.8–3.9] | 18.0 [15.0–22.0] |
| Meteor | v24.15.0 | upstream | 100 | 3/3 | 126.5 [126.2–127.6] | 187.0 [181.6–188.3] | 188.9 [184.5–191.2] | 8.0 [7.7–8.1] | 25.0 [24.0–25.0] |
| Meteor | v24.15.0 | hello | 1000 | 3/3 | 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] |
| Meteor | v24.15.0 | catalog | 1000 | 3/3 | 124.1 [123.3–124.2] | 167.6 [167.6–172.5] | 168.0 [167.7–173.2] | 15.2 [15.1–15.9] | 10.0 [9.0–10.0] |
| Meteor | v24.15.0 | validate | 1000 | 3/3 | 125.2 [124.6–126.1] | 174.9 [173.8–175.0] | 176.3 [175.0–176.6] | 14.8 [14.6–14.9] | 10.0 [9.0–13.0] |
| Meteor | v24.15.0 | upstream | 1000 | 3/3 | 127.8 [127.2–128.3] | 213.9 [213.8–217.2] | 124.5 [122.1–126.7] | 38.2 [36.8–41.4] | 18.0 [17.0–19.0] |
| AdonisJS | v24.15.0 | hello | 100 | 3/3 | 114.9 [113.9–115.3] | 143.4 [143.0–149.2] | 144.3 [143.1–149.4] | 2.5 [2.3–2.5] | 9.0 [9.0–10.0] |
| AdonisJS | v24.15.0 | catalog | 100 | 3/3 | 114.4 [113.7–116.0] | 142.7 [142.7–142.9] | 143.6 [142.9–144.3] | 3.0 [3.0–3.1] | 13.0 [12.0–13.0] |
| AdonisJS | v24.15.0 | validate | 100 | 3/3 | 114.5 [114.3–115.0] | 147.0 [146.6–147.4] | 148.5 [148.1–148.5] | 3.0 [2.9–3.0] | 12.0 [12.0–13.0] |
| AdonisJS | v24.15.0 | upstream | 100 | 3/3 | 115.9 [112.8–116.2] | 195.2 [194.7–198.7] | 197.2 [194.8–199.7] | 6.3 [6.1–6.3] | 20.0 [20.0–21.0] |
| AdonisJS | v24.15.0 | hello | 1000 | 3/3 | 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] |
| AdonisJS | v24.15.0 | catalog | 1000 | 3/3 | 113.7 [113.2–114.4] | 149.3 [149.2–151.7] | 151.8 [151.7–153.0] | 14.5 [14.4–14.7] | 9.0 [8.0–9.0] |
| AdonisJS | v24.15.0 | validate | 1000 | 3/3 | 115.2 [115.1–115.7] | 149.4 [149.0–149.8] | 149.4 [148.9–149.5] | 13.7 [13.6–14.3] | 9.0 [7.0–10.0] |
| AdonisJS | v24.15.0 | upstream | 1000 | 3/3 | 115.0 [114.8–115.5] | 208.4 [203.9–221.8] | 212.1 [206.0–223.5] | 37.8 [35.6–38.7] | 15.0 [15.0–17.0] |
| NestJS · Express | v24.15.0 | hello | 100 | 3/3 | 99.8 [99.7–100.9] | 126.2 [125.2–130.1] | 126.4 [125.2–130.1] | 2.1 [2.1–2.2] | 7.0 [7.0–8.0] |
| NestJS · Express | v24.15.0 | catalog | 100 | 3/3 | 100.3 [99.8–100.4] | 127.1 [127.0–127.7] | 127.3 [127.0–127.8] | 2.5 [2.5–2.6] | 10.0 [10.0–10.0] |
| NestJS · Express | v24.15.0 | validate | 100 | 3/3 | 100.4 [100.3–101.0] | 130.0 [129.3–130.4] | 130.5 [130.5–130.9] | 2.4 [2.3–2.4] | 9.0 [8.0–13.0] |
| NestJS · Express | v24.15.0 | upstream | 100 | 3/3 | 102.4 [101.9–102.9] | 188.1 [183.4–189.5] | 190.1 [185.1–192.4] | 6.2 [6.1–6.2] | 20.0 [20.0–22.0] |
| NestJS · Express | v24.15.0 | hello | 1000 | 3/3 | 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] |
| NestJS · Express | v24.15.0 | catalog | 1000 | 3/3 | 100.8 [100.3–101.1] | 129.2 [127.9–132.9] | 129.4 [129.2–132.9] | 11.4 [11.3–11.5] | 11.0 [8.0–11.0] |
| NestJS · Express | v24.15.0 | validate | 1000 | 3/3 | 101.3 [101.2–101.4] | 132.2 [131.7–132.7] | 132.2 [131.7–132.7] | 10.7 [10.7–11.0] | 7.0 [6.0–8.0] |
| NestJS · Express | v24.15.0 | upstream | 1000 | 3/3 | 103.0 [101.1–103.4] | 201.2 [201.0–201.7] | 201.2 [201.1–201.7] | 37.1 [31.8–38.3] | 16.0 [16.0–17.0] |
| Total.js 5 | v24.15.0 | hello | 100 | 3/3 | 63.1 [63.0–63.2] | 94.6 [93.9–95.2] | 103.2 [103.1–104.0] | 1.6 [1.5–1.6] | 5.0 [5.0–6.0] |
| Total.js 5 | v24.15.0 | catalog | 100 | 3/3 | 63.3 [63.3–63.5] | 99.9 [99.9–100.7] | 107.5 [107.2–108.8] | 2.0 [1.9–2.1] | 7.0 [6.0–8.0] |
| Total.js 5 | v24.15.0 | validate | 100 | 3/3 | 63.2 [63.2–63.2] | 93.4 [92.2–94.2] | 96.7 [94.7–101.4] | 1.9 [1.8–2.0] | 7.0 [6.0–7.0] |
| Total.js 5 | v24.15.0 | upstream | 100 | 3/3 | 69.5 [69.4–69.5] | 168.3 [166.0–169.2] | 169.8 [167.4–172.5] | 5.6 [5.4–5.6] | 18.0 [18.0–18.0] |
| Total.js 5 | v24.15.0 | hello | 1000 | 3/3 | 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] |
| Total.js 5 | v24.15.0 | catalog | 1000 | 3/3 | 63.3 [63.3–63.5] | 175.0 [173.3–175.6] | 175.5 [173.7–181.0] | 9.9 [9.9–9.9] | 6.0 [5.0–9.0] |
| Total.js 5 | v24.15.0 | validate | 1000 | 3/3 | 63.2 [63.0–63.5] | 169.2 [164.2–169.4] | 171.4 [170.9–171.4] | 9.1 [9.0–9.2] | 22.0 [6.0–27.0] |
| Total.js 5 | v24.15.0 | upstream | 1000 | 3/3 | 68.4 [68.1–69.2] | 205.0 [203.3–206.0] | 207.9 [203.8–210.7] | 36.4 [30.2–36.8] | 23.0 [22.0–24.0] |

[Surové merania](/benchmarks/linux-20261017/general.json)

[Zmrazené zdroje a zámky závislostí](/benchmarks/linux-20261017/sources.tar.gz)

[Zaznamenaná správa](/benchmarks/linux-20261017/general-report.md)

[CSV podľa scenára](/benchmarks/linux-20261017/general.csv)

## Reprodukovať a preveriť

Použite prázdny adresár s Dockerom (kontajnery Linux), curl a tar. Node.js na hostiteľovi nepotrebujete: kontrola kontrolného súčtu aj testy používajú Node 24.15.0 v Dockeri. Prvé zostavenie sťahuje závislosti a kompiluje Meteor, čo môže trvať niekoľko minút. Príprava vyžaduje internet; testovacie kontajnery nemajú vonkajšiu sieť. Každý meraný scenár trvá približne šesť minút.

Kompletný kit spúšťa všetkých osem adaptérov na Node 24.15.0 v kontajneroch Linux. Obsahuje spúšťač, adaptéry, zámky závislostí a pokyny na zostavenie Meteoru. Publikované merania si zachovávajú pôvodné verzie runtime a pôvodný archív zdrojov, dostupné v dôkazoch; tento kit zjednocuje len nové spustenia.

[Stiahnuť kompletný testovací kit](https://forge.totaljs.es/benchmarks/node-24.15.0/sources.tar.gz)

1. Stiahnuť a pripraviť. Odkaz obsahuje spúšťač, adaptéry a zámky závislostí; nie je potrebná inštalácia Forge ani klonovanie repozitára. V prázdnom adresári spustite nasledujúce príkazy. Ak ste stiahli tlačidlom, ponechajte názov sources.tar.gz a vynechajte curl.

```bash
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. Skontrolovať inštaláciu (približne 15–30 sekúnd). Tento krátky test vytvorí smoke.json a overí jeho zaznamenané vstupy; nie je to publikovateľný výkonnostný výsledok.

```bash
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. Spustiť a overiť zvolené meranie. Výsledky sa uložia do results/my-run.json vo zvolenom adresári benchmarks. Spúšťač odmieta prepísať existujúci výstup: pri opakovaní použite iný názov súboru. Overenie kontroluje úplnosť a vstupy, nie zhodu s publikovanými hodnotami.

```bash
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
```

[JSON](/benchmarks/summary.json) · [Revízia integrity a prostredia](/benchmarks/linux-20261017/review.json) · [SHA-256](/benchmarks/linux-20261017/SHA256SUMS.txt)
