Forge
fr

Forge / Linux · 17–18 Oct 2026

Benchmarks

Le même travail, le même trafic. Explorez les mesures enregistrées, comprenez la méthode et reproduisez chaque test.

192Mesures terminées
3Répétitions par scénario
0 / 0 / 0Erreurs, délais dépassés ou réponses en échec
Node.js 24Kit: Node.js 24.15.0192 · Mesures terminéesTerminée: 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

Comparer le même scénario

RSS pendant la charge · MiB

Les barres montrent la médiane de trois répétitions. Les moustaches indiquent leur minimum et leur maximum. La mémoire est le RSS du processus en MiB ; chaque axe part de zéro. L’ordre des frameworks est fixe, ce n’est pas un classement.

RSS pendant la charge · 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
Toutes les métriques de ce scénario
FrameworkRSS initial · MiBRSS en charge · MiBRSS après la charge · MiBCPU · %Latence p99 · msCouverture de la cible · %Exécutions saines
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

Les valeurs sont la médiane [minimum–maximum] des répétitions. Chaque valeur de RSS est une médiane au sein de la phase ; les pics échantillonnés restent dans les données brutes. La valeur initiale suit les requêtes de disponibilité : ce n’est donc pas une mémoire vierge sans requêtes. Le CPU est un pourcentage d’un CPU logique pendant la fenêtre échantillonnée. Le p99 décrit les requêtes terminées ; lisez-le avec les erreurs et la couverture de la cible.

La mémoire pendant une mesure

Un processus neuf, échantillonné chaque seconde. Les fenêtres ombrées repèrent la charge et la récupération ; l’échauffement et la stabilisation précèdent la charge. Le RSS inclut le runtime, le tas et la mémoire native. Ce n’est pas le tas JavaScript actif.

La mémoire pendant une mesure · Total.js 5 · 10501001502000 s23 s45 s68 s90 s113 sMiB
RSSJS heapChargeRécupération

Télécharger le kit et préparer votre ordinateur

À exécuter après la préparation du kit de 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

La commande utilise la suite figée de l’exécution choisie. Alignez le matériel, les limites des conteneurs et l’activité en arrière-plan avant de comparer une nouvelle exécution. Vérifiez ensuite avec le v2/verify.cjs correspondant.

Comment lire le résultat

Comparez la même charge au même rythme cible et lisez ensemble la latence, le CPU, la mémoire, les erreurs et la couverture de la cible. La version du runtime compte aussi. Ces mesures ne démontrent pas qu’un framework consomme toujours moins de ressources. Total.js 4 et 5 sont présentés séparément ; chacun utilise son implémentation et son runtime enregistrés.

Ce qui a été mesuré

Huit adaptateurs, quatre charges et des cibles communes de 100 et 1 000 requêtes/s : 192 mesures. Chaque mesure démarre un processus de production neuf : vérification de la réponse, 1,5 s de référence, 15 s d’échauffement, 6 s de stabilisation, 60 s de charge et 30 s de récupération. Les trois répétitions sont conservées. Les adaptateurs ont été mesurés l’un après l’autre. Le contenu des réponses réussies est vérifié avant et après la charge ; le générateur demande jusqu’à 32 connexions.

Total5 utilise un NEWSCHEMA compact et un contrôleur direct pour valider le JSON ; les petites réponses JSON sont renvoyées directement par le contrôleur. La comparaison contient des scénarios complets enregistrés, jamais le meilleur résultat chiffré. Meteor utilise son bundle de production côté serveur uniquement ; NestJS son adaptateur Express. Les validateurs natifs couvrent le contenu mesuré ; le rejet et la conversion peuvent différer d’un framework à l’autre.

Environnement

Hôte Linux x64 partagé, Intel Core i7-6700. Chaque conteneur de mesure était limité à 2 CPU logiques et 2 GiB, sans réseau externe ni port publié. Le générateur et la dépendance simulée partageaient le conteneur. Node 24.14.1 a servi pour Total4, Express, Fastify et Node http ; Node 24.15.0 pour Total5, Meteor, AdonisJS et NestJS, en accord avec le runtime du bundle Meteor. Les versions du runtime sont indiquées à côté de chaque framework : les différences ne peuvent pas être attribuées au seul framework. Les services de production sont restés sur l’hôte.

Ce que ces résultats ne démontrent pas

Il s’agit d’une expérience à débit fixe et en boucle fermée, pas d’un classement du débit maximal. Atteindre la cible configurée ne démontre pas comment un adaptateur gère des arrivées indépendantes ou la saturation. Une certaine limitation du CPU par quota a eu lieu ; elle est consignée dans la revue. Trois courtes répétitions ne démontrent ni la stabilité à long terme, ni l’absence de fuites de mémoire, ni la sécurité en production, ni le comportement de Flow, ni l’usage mémoire sur Raspberry Pi. Le ramasse-miettes n’a pas été forcé. Le RSS peut rester alloué après la fin du trafic.

Une cellule est saine lorsque les requêtes terminées atteignent au moins 95 % du débit cible × la durée du générateur, que le p99 est d’au plus 250 ms et que les nombres d’erreurs, de délais dépassés et de réponses non 2xx sont nuls. Ce seuil n’affirme pas une capacité maximale égale.

Preuves d’origine

Revue d’intégrité et d’environnement · Sommes SHA-256 · JSON · Markdown

Reproduire et vérifier

Utilisez un répertoire vide avec Docker (conteneurs Linux), curl et tar. Node.js n’est pas nécessaire sur l’hôte : la vérification de la somme de contrôle et la suite de tests utilisent Node 24.15.0 dans Docker. La première construction télécharge des dépendances et compile Meteor, ce qui peut prendre plusieurs minutes. La préparation nécessite internet ; les conteneurs de test n’ont pas de réseau externe. Chaque scénario mesuré dure environ six minutes.

Le kit exécute les huit adaptateurs sur Node v24.15.0. Les mesures publiées conservent leurs runtimes d’origine, indiqués dans le tableau.

Télécharger le kit de test complet

1. Télécharger et préparer. Le lien contient l’exécuteur, les adaptateurs et les verrous de dépendances ; aucune installation de Forge ni clonage de dépôt n’est nécessaire. Dans un répertoire vide, exécutez les commandes suivantes. Si vous avez téléchargé avec le bouton, gardez le nom sources.tar.gz et sautez 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. Vérifier l’installation (environ 15 à 30 secondes). Ce court test produit smoke.json et vérifie ses entrées enregistrées ; ce n’est pas un résultat de performance publiable.

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. Exécuter et vérifier la mesure choisie. Les résultats sont enregistrés dans results/my-run.json, dans le répertoire benchmarks choisi. L’exécuteur refuse d’écraser une sortie existante : utilisez un autre nom de fichier pour une répétition. La vérification contrôle l’exhaustivité et les entrées, pas l’égalité avec les chiffres publiés.

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