Forge / Linux · 17–18 Oct 2026
Benchmarks
Η ίδια εργασία, η ίδια κίνηση. Εξερευνήστε τις καταγεγραμμένες μετρήσεις, κατανοήστε τη μέθοδο και επαναλάβετε κάθε δοκιμή.
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
Συγκρίνετε το ίδιο σενάριο
RSS κατά τον φόρτο · MiB
Οι μπάρες δείχνουν τη διάμεσο τριών επαναλήψεων. Τα μουστάκια δείχνουν το ελάχιστο και το μέγιστο. Η μνήμη είναι το RSS της διεργασίας σε MiB· κάθε άξονας ξεκινά από το μηδέν. Η σειρά των frameworks είναι σταθερή, δεν είναι κατάταξη.
| Framework | Αρχικό RSS · MiB | RSS υπό φόρτο · MiB | RSS μετά τον φόρτο · MiB | CPU · % | Καθυστέρηση p99 · ms | Κάλυψη στόχου · % | Υγιείς εκτελέσεις |
|---|---|---|---|---|---|---|---|
| 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 | |||||||
Οι τιμές είναι η διάμεσος [ελάχιστο–μέγιστο] των επαναλήψεων. Κάθε τιμή RSS είναι διάμεσος εντός της φάσης· οι δειγματοληπτικές κορυφές παραμένουν στα ακατέργαστα δεδομένα. Η αρχική τιμή έπεται των αιτημάτων ετοιμότητας, άρα δεν είναι μνήμη χωρίς κανένα αίτημα. Η CPU είναι ποσοστό ενός λογικού CPU στο δειγματοληπτικό παράθυρο. Το p99 περιγράφει τα ολοκληρωμένα αιτήματα· διαβάστε το μαζί με τα σφάλματα και την κάλυψη του στόχου.
Η μνήμη κατά τη διάρκεια μιας μέτρησης
Μία νέα διεργασία, με δειγματοληψία κάθε δευτερόλεπτο. Τα σκιασμένα παράθυρα δείχνουν τον φόρτο και την ανάκαμψη· πριν από τον φόρτο προηγούνται η προθέρμανση και η σταθεροποίηση. Το RSS περιλαμβάνει το runtime, το heap και την εγγενή μνήμη. Δεν είναι το ενεργό heap της JavaScript.
Λήψη του κιτ και προετοιμασία του υπολογιστή σας
Εκτελέστε μετά την προετοιμασία του κιτ δοκιμών
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Η εντολή χρησιμοποιεί την παγωμένη σουίτα της επιλεγμένης εκτέλεσης. Εξισώστε υλικό, όρια κοντέινερ και δραστηριότητα παρασκηνίου πριν συγκρίνετε μια νέα εκτέλεση. Επαληθεύστε στη συνέχεια με το αντίστοιχο v2/verify.cjs.
Πώς να διαβάσετε το αποτέλεσμα
Συγκρίνετε τον ίδιο φόρτο με τον ίδιο στόχο ρυθμού και διαβάστε μαζί την καθυστέρηση, την CPU, τη μνήμη, τα σφάλματα και την κάλυψη του στόχου. Σημασία έχει και η έκδοση του runtime. Αυτές οι μετρήσεις δεν αποδεικνύουν ότι ένα framework καταναλώνει πάντα λιγότερους πόρους. Τα Total.js 4 και 5 εμφανίζονται χωριστά· καθένα χρησιμοποιεί την καταγεγραμμένη υλοποίηση και το runtime του.
Τι μετρήθηκε
Οκτώ προσαρμογείς, τέσσερις φόρτοι και κοινοί στόχοι 100 και 1.000 αιτημάτων/s: 192 μετρήσεις. Κάθε μέτρηση ξεκινά μια νέα διεργασία παραγωγής: έλεγχος απάντησης, 1,5 s βάσης, 15 s προθέρμανσης, 6 s σταθεροποίησης, 60 s φόρτου και 30 s ανάκαμψης. Διατηρούνται και οι τρεις επαναλήψεις. Οι προσαρμογείς μετρήθηκαν διαδοχικά. Το περιεχόμενο των επιτυχημένων απαντήσεων ελέγχεται πριν και μετά τον φόρτο· η γεννήτρια ζητά έως 32 συνδέσεις.
Το Total5 χρησιμοποιεί συμπαγές NEWSCHEMA και άμεσο controller για την επικύρωση JSON· οι μικρές απαντήσεις JSON επιστρέφονται απευθείας από τον controller. Η σύγκριση περιέχει πλήρη καταγεγραμμένα σενάρια, ποτέ το καλύτερο αριθμητικό αποτέλεσμα. Το Meteor χρησιμοποιεί το bundle παραγωγής μόνο για τον διακομιστή· το NestJS τον προσαρμογέα Express. Οι εγγενείς επικυρωτές καλύπτουν το μετρούμενο περιεχόμενο· η απόρριψη και οι μετατροπές μπορεί να διαφέρουν μεταξύ των frameworks.
Περιβάλλον
Κοινόχρηστος διακομιστής Linux x64, Intel Core i7-6700. Κάθε κοντέινερ μέτρησης περιοριζόταν σε 2 λογικά CPU και 2 GiB, χωρίς εξωτερικό δίκτυο και δημοσιευμένες θύρες. Η γεννήτρια και η προσομοιωμένη εξάρτηση μοιράζονταν το κοντέινερ. Το Node 24.14.1 χρησιμοποιήθηκε για τα Total4, Express, Fastify και Node http· το Node 24.15.0 για τα Total5, Meteor, AdonisJS και NestJS, σύμφωνα με το runtime του bundle του Meteor. Οι εκδόσεις runtime εμφανίζονται δίπλα σε κάθε framework: οι διαφορές δεν μπορούν να αποδοθούν μόνο στο framework. Οι υπηρεσίες παραγωγής παρέμειναν στον διακομιστή.
Τι δεν αποδεικνύουν αυτά τα αποτελέσματα
Πρόκειται για πείραμα με σταθερό ρυθμό και κλειστό βρόχο, όχι για κατάταξη μέγιστης διεκπεραίωσης. Η επίτευξη του ρυθμισμένου στόχου δεν αποδεικνύει πώς χειρίζεται ένας προσαρμογέας ανεξάρτητες αφίξεις ή κορεσμό. Υπήρξε κάποιος περιορισμός CPU λόγω ποσόστωσης, καταγεγραμμένος στον έλεγχο. Τρεις σύντομες επαναλήψεις δεν αποδεικνύουν μακροπρόθεσμη σταθερότητα, απουσία διαρροών μνήμης, ασφάλεια παραγωγής, συμπεριφορά του Flow ή χρήση μνήμης στο Raspberry Pi. Δεν επιβλήθηκε συλλογή απορριμμάτων. Το RSS μπορεί να παραμείνει δεσμευμένο μετά το τέλος της κίνησης.
Ένα κελί είναι υγιές όταν τα ολοκληρωμένα αιτήματα φτάνουν τουλάχιστον το 95% του στόχου × τη διάρκεια της γεννήτριας, το p99 δεν ξεπερνά τα 250 ms και οι αριθμοί σφαλμάτων, λήξεων χρόνου και απαντήσεων εκτός 2xx είναι μηδέν. Αυτό το όριο δεν ισχυρίζεται ίση μέγιστη χωρητικότητα.
Αρχικά αποδεικτικά στοιχεία
Έλεγχος ακεραιότητας και περιβάλλοντος · Αθροίσματα ελέγχου SHA-256 · JSON · Markdown
Αναπαραγωγή και έλεγχος
Χρησιμοποιήστε έναν κενό φάκελο με Docker (κοντέινερ Linux), curl και tar. Το Node.js δεν χρειάζεται στον υπολογιστή: ο έλεγχος του αθροίσματος και η σουίτα δοκιμών χρησιμοποιούν Node 24.15.0 μέσα στο Docker. Η πρώτη κατασκευή κατεβάζει εξαρτήσεις και μεταγλωττίζει το Meteor, κάτι που μπορεί να πάρει αρκετά λεπτά. Η προετοιμασία απαιτεί internet· τα κοντέινερ δοκιμών δεν έχουν εξωτερικό δίκτυο. Κάθε μετρούμενο σενάριο διαρκεί περίπου έξι λεπτά.
Το κιτ εκτελεί και τους οκτώ προσαρμογείς σε Node v24.15.0. Οι δημοσιευμένες μετρήσεις διατηρούν τα αρχικά runtime τους, που φαίνονται στον πίνακα.
1. Λήψη και προετοιμασία. Ο σύνδεσμος περιέχει τον εκτελεστή, τους προσαρμογείς και τα κλειδώματα εξαρτήσεων· δεν χρειάζεται εγκατάσταση του Forge ούτε κλωνοποίηση αποθετηρίου. Σε έναν κενό φάκελο, εκτελέστε τις παρακάτω εντολές. Αν κατεβάσατε με το κουμπί, κρατήστε το όνομα sources.tar.gz και παραλείψτε το 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. Έλεγχος της εγκατάστασης (περίπου 15–30 δευτερόλεπτα). Αυτή η σύντομη δοκιμή δημιουργεί το 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/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. Εκτέλεση και επαλήθευση της επιλεγμένης μέτρησης. Τα αποτελέσματα αποθηκεύονται στο results/my-run.json μέσα στον επιλεγμένο φάκελο benchmarks. Ο εκτελεστής αρνείται να αντικαταστήσει υπάρχουσα έξοδο: για επανάληψη χρησιμοποιήστε άλλο όνομα αρχείου. Η επαλήθευση ελέγχει την πληρότητα και τις εισόδους, όχι την ισότητα με τους δημοσιευμένους αριθμούς.
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