Forge / Linux · 17–18 Oct 2026
Benchmarks
Ta sama praca, ten sam ruch. Poznaj zapisane pomiary, zrozum metodę i powtórz każdy 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
Porównaj ten sam scenariusz
RSS podczas obciążenia · MiB
Słupki pokazują medianę z trzech powtórzeń. Wąsy pokazują ich minimum i maksimum. Pamięć to RSS procesu w MiB; każda oś zaczyna się od zera. Kolejność frameworków jest stała i nie jest rankingiem.
| Framework | RSS początkowy · MiB | RSS pod obciążeniem · MiB | RSS po obciążeniu · MiB | CPU · % | Opóźnienie p99 · ms | Pokrycie celu · % | Zdrowe przebiegi |
|---|---|---|---|---|---|---|---|
| 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 | |||||||
Wartości to mediana [minimum–maksimum] z powtórzeń. Każda wartość RSS jest medianą w obrębie fazy; próbkowane szczyty pozostają w danych surowych. Wartość początkowa następuje po żądaniach gotowości, więc nie jest pamięcią bez żadnych żądań. CPU to procent jednego logicznego CPU w próbkowanym oknie. p99 opisuje zakończone żądania; czytaj je razem z błędami i pokryciem celu.
Pamięć podczas jednego pomiaru
Jeden nowy proces, próbkowany co sekundę. Zacienione okna oznaczają obciążenie i powrót do normy; przed obciążeniem następuje rozgrzewka i ustabilizowanie. RSS obejmuje runtime, stertę i pamięć natywną. To nie jest aktywna sterta JavaScript.
Pobierz zestaw i przygotuj komputer
Uruchom po przygotowaniu zestawu testowego
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.jsonPolecenie używa zamrożonego zestawu wybranego przebiegu. Ujednolić sprzęt, limity kontenerów i aktywność w tle przed porównaniem ponownego uruchomienia. Po zakończeniu zweryfikuj odpowiednim v2/verify.cjs.
Jak czytać wynik
Porównuj to samo obciążenie przy tym samym tempie docelowym i czytaj razem opóźnienie, CPU, pamięć, błędy i pokrycie celu. Ważna jest też wersja runtime. Te pomiary nie dowodzą, że jeden framework zawsze zużywa mniej zasobów. Total.js 4 i 5 pokazano osobno; każdy używa zapisanej implementacji i runtime.
Co zmierzono
Osiem adapterów, cztery obciążenia i wspólne cele 100 i 1000 żądań/s: 192 pomiary. Każdy pomiar uruchamia nowy proces produkcyjny: sprawdzenie odpowiedzi, 1,5 s bazy, 15 s rozgrzewki, 6 s ustabilizowania, 60 s obciążenia i 30 s powrotu do normy. Zachowano wszystkie trzy powtórzenia. Adaptery mierzono kolejno. Treść udanych odpowiedzi jest sprawdzana przed obciążeniem i po nim; generator żąda do 32 połączeń.
Total5 używa kompaktowego NEWSCHEMA i bezpośredniego kontrolera do walidacji JSON; małe odpowiedzi JSON zwraca bezpośrednio kontroler. Porównanie zawiera pełne zapisane scenariusze, nigdy najlepszy wynik liczbowy. Meteor używa swojego produkcyjnego bundla tylko serwerowego; NestJS używa adaptera Express. Natywne walidatory obejmują mierzoną treść; odrzucanie i konwersje mogą się różnić między frameworkami.
Środowisko
Współdzielony host Linux x64, Intel Core i7-6700. Każdy kontener pomiarowy był ograniczony do 2 logicznych CPU i 2 GiB, bez sieci zewnętrznej i opublikowanych portów. Generator i symulowana zależność dzieliły kontener. Node 24.14.1 użyto dla Total4, Express, Fastify i Node http; Node 24.15.0 dla Total5, Meteor, AdonisJS i NestJS, zgodnie z runtime bundla Meteor. Wersje runtime są pokazane przy każdym frameworku: różnic nie można przypisać samemu frameworkowi. Usługi produkcyjne pozostały na hoście.
Czego te wyniki nie dowodzą
To eksperyment ze stałym tempem i zamkniętą pętlą, a nie ranking maksymalnej przepustowości. Osiągnięcie ustawionego celu nie dowodzi, jak adapter radzi sobie z niezależnymi nadejściami czy nasyceniem. Wystąpiło pewne ograniczanie CPU przez limit, odnotowane w przeglądzie. Trzy krótkie powtórzenia nie dowodzą długoterminowej stabilności, braku wycieków pamięci, bezpieczeństwa produkcyjnego, zachowania Flow ani użycia pamięci na Raspberry Pi. Nie wymuszano odśmiecania pamięci. RSS może pozostać zajęte po ustaniu ruchu.
Komórka jest zdrowa, gdy zakończone żądania osiągają co najmniej 95% celu × czas pracy generatora, p99 nie przekracza 250 ms, a liczby błędów, przekroczeń czasu i odpowiedzi innych niż 2xx wynoszą zero. Ten próg nie twierdzi, że wszystkie mają równą maksymalną pojemność.
Oryginalne dowody
Przegląd integralności i środowiska · Sumy kontrolne SHA-256 · JSON · Markdown
Odtwórz i sprawdź
Użyj pustego katalogu z Dockerem (kontenery Linux), curl i tar. Node.js nie jest potrzebny na hoście: sprawdzenie sumy kontrolnej i zestaw testów używają Node 24.15.0 w Dockerze. Pierwsze budowanie pobiera zależności i kompiluje Meteor, co może potrwać kilka minut. Przygotowanie wymaga internetu; kontenery testowe nie mają sieci zewnętrznej. Każdy mierzony scenariusz trwa około sześciu minut.
Zestaw uruchamia wszystkie osiem adapterów na Node v24.15.0. Opublikowane pomiary zachowują oryginalne runtime, pokazane w tabeli.
1. Pobierz i przygotuj. Odnośnik zawiera program uruchamiający, adaptery i blokady zależności; nie trzeba instalować Forge ani klonować repozytorium. W pustym katalogu uruchom poniższe polecenia. Jeśli pobrano przyciskiem, zachowaj nazwę sources.tar.gz i pomiń 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. Sprawdź instalację (około 15–30 sekund). Ten krótki test tworzy smoke.json i weryfikuje jego zapisane dane wejściowe; nie jest to wynik wydajności do publikacji.
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. Uruchom i zweryfikuj wybrany pomiar. Wyniki są zapisywane w results/my-run.json w wybranym katalogu benchmarks. Program odmawia nadpisania istniejącego wyniku: do powtórzenia użyj innej nazwy pliku. Weryfikacja sprawdza kompletność i dane wejściowe, nie zgodność z opublikowanymi liczbami.
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