Forge
it

Forge / Linux · 17–18 Oct 2026

Benchmarks

Lo stesso lavoro, lo stesso traffico. Esplora le misurazioni registrate, capisci il metodo e riproduci ogni test.

192Misurazioni completate
3Ripetizioni per scenario
0 / 0 / 0Errori, timeout o risposte fallite
Node.js 24Kit: Node.js 24.15.0192 · Misurazioni completateTerminata: 2026-10-18 13:56:39 UTC

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

Confronta lo stesso scenario

RSS durante il carico · MiB

Le barre mostrano la mediana di tre ripetizioni. Le linee indicano minimo e massimo. La memoria è l’RSS del processo in MiB; ogni asse parte da zero. L’ordine dei framework è fisso, non è una classifica.

RSS durante il carico · MiB0.047.995.8143.7191.6Total.js 4: 159.3 [150.1–167.0]Total.js 4159.3Total.js 5: 165.7 [164.9–166.7]Total.js 5165.7Express: 90.8 [90.4–91.5]Express90.8Fastify: 91.2 [91.0–91.6]Fastify91.2Node.js http: 67.9 [67.5–69.8]Node.js http67.9Meteor: 168.6 [167.6–171.1]Meteor168.6AdonisJS: 145.3 [144.6–149.7]AdonisJS145.3NestJS · Express: 129.6 [129.4–130.0]NestJS · Express129.6
Tutte le metriche di questo scenario
FrameworkRSS iniziale · MiBRSS sotto carico · MiBRSS dopo il carico · MiBCPU · %Latenza p99 · msCopertura dell’obiettivo · %Esecuzioni sane
Total.js 461.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 562.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
Express74.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
Fastify75.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 http50.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
Meteor124.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
AdonisJS114.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 · Express100.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.js
Total.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

I valori sono la mediana [minimo–massimo] delle ripetizioni. Ogni valore di RSS è una mediana all’interno della fase; i picchi campionati restano nei dati grezzi. Il valore iniziale segue le richieste di disponibilità, quindi non è memoria priva di richieste. La CPU è una percentuale di una CPU logica nella finestra campionata. Il p99 descrive le richieste completate; leggilo insieme agli errori e alla copertura dell’obiettivo.

La memoria durante una misurazione

Un processo nuovo, campionato ogni secondo. Le finestre ombreggiate indicano carico e recupero; riscaldamento e assestamento precedono il carico. L’RSS comprende runtime, heap e memoria nativa. Non è l’heap JavaScript in uso.

La memoria durante una misurazione · Total.js 5 · 10501001502000 s23 s45 s68 s90 s113 sMiB
RSSJS heapCaricoRecupero

Scarica il kit e prepara il tuo computer

Da eseguire dopo aver preparato il kit di test

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

Il comando usa la suite congelata dell’esecuzione scelta. Allinea hardware, limiti dei container e attività in background prima di confrontare una nuova esecuzione. Verifica poi con il v2/verify.cjs corrispondente.

Come leggere il risultato

Confronta lo stesso carico allo stesso ritmo obiettivo e leggi insieme latenza, CPU, memoria, errori e copertura dell’obiettivo. Conta anche la versione del runtime. Queste misurazioni non dimostrano che un framework usi sempre meno risorse. Total.js 4 e 5 sono mostrati separatamente; ciascuno usa la propria implementazione e il proprio runtime registrati.

Che cosa è stato misurato

Otto adattatori, quattro carichi e obiettivi comuni di 100 e 1.000 richieste/s: 192 misurazioni. Ogni misurazione avvia un processo di produzione nuovo: controllo della risposta, 1,5 s di base, 15 s di riscaldamento, 6 s di assestamento, 60 s di carico e 30 s di recupero. Si conservano tutte e tre le ripetizioni. Gli adattatori sono stati misurati in sequenza. Il contenuto delle risposte riuscite viene verificato prima e dopo il carico; il generatore richiede fino a 32 connessioni.

Total5 usa un NEWSCHEMA compatto e un controller diretto per validare il JSON; le piccole risposte JSON sono restituite direttamente dal controller. Il confronto contiene scenari completi registrati, mai il miglior risultato numerico. Meteor usa il suo bundle di produzione solo server; NestJS il suo adattatore Express. I validatori nativi coprono il contenuto misurato; rifiuto e conversione possono differire tra i framework.

Ambiente

Host Linux x64 condiviso, Intel Core i7-6700. Ogni container di misurazione era limitato a 2 CPU logiche e 2 GiB, senza rete esterna né porte pubblicate. Il generatore e la dipendenza simulata condividevano il container. Node 24.14.1 è stato usato per Total4, Express, Fastify e Node http; Node 24.15.0 per Total5, Meteor, AdonisJS e NestJS, in linea con il runtime del bundle di Meteor. Le versioni del runtime sono mostrate accanto a ogni framework: le differenze non possono essere attribuite al solo framework. I servizi di produzione sono rimasti sull’host.

Che cosa questi risultati non dimostrano

È un esperimento a ritmo fisso e a ciclo chiuso, non una classifica della capacità massima. Raggiungere l’obiettivo configurato non dimostra come un adattatore gestisca arrivi indipendenti o saturazione. C’è stata una certa limitazione della CPU per quota, registrata nella revisione. Tre brevi ripetizioni non dimostrano stabilità a lungo termine, assenza di perdite di memoria, sicurezza in produzione, comportamento di Flow né uso di memoria su Raspberry Pi. Non è stata forzata la garbage collection. L’RSS può restare allocato dopo la fine del traffico.

Una cella è sana quando le richieste completate raggiungono almeno il 95 % dell’obiettivo × la durata del generatore, il p99 non supera 250 ms e i conteggi di errori, timeout e risposte non 2xx sono zero. Questa soglia non afferma una capacità massima uguale.

Evidenze originali

Revisione di integrità e ambiente · Checksum SHA-256 · JSON · Markdown

Riprodurre e verificare

Usa una cartella vuota con Docker (container Linux), curl e tar. Node.js non serve sull’host: sia la verifica del checksum sia la suite di test usano Node 24.15.0 dentro Docker. La prima compilazione scarica le dipendenze e compila Meteor, e può richiedere diversi minuti. La preparazione richiede internet; i container di test non hanno rete esterna. Ogni scenario misurato richiede circa sei minuti.

Il kit esegue tutti e otto gli adattatori su Node v24.15.0. Le misurazioni pubblicate conservano i runtime originali, indicati nella tabella.

Scarica il kit di test completo

1. Scarica e prepara. Il link contiene il runner, gli adattatori e i lock delle dipendenze; non serve installare Forge né clonare un repository. In una cartella vuota, esegui i comandi seguenti. Se hai scaricato con il pulsante, mantieni il nome sources.tar.gz e salta 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. Verifica l’installazione (circa 15–30 secondi). Questo breve test produce smoke.json e ne verifica gli input registrati; non è un risultato di prestazioni pubblicabile.

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. Esegui e verifica la misurazione scelta. I risultati vengono salvati in results/my-run.json nella cartella benchmarks selezionata. Il runner rifiuta di sovrascrivere un output esistente: usa un altro nome di file per ripetere. La verifica controlla completezza e input, non l’uguaglianza con le cifre pubblicate.

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