Heim  >  Artikel  >  Web-Frontend  >  Encore.ts – Schnellere Kaltstarts als NestJS und Fastify

Encore.ts – Schnellere Kaltstarts als NestJS und Fastify

WBOY
WBOYOriginal
2024-09-05 06:38:03495Durchsuche

Vor ein paar Monaten haben wir Encore.ts veröffentlicht – ein Open-Source-Backend-Framework für TypeScript.

Da es bereits viele Frameworks gibt, möchten wir einige der außergewöhnlichen Designentscheidungen, die wir getroffen haben, mitteilen und wie sie zu bemerkenswerten Leistungszahlen führen.

Wir haben kürzlich Leistungsbenchmarks veröffentlicht, die zeigen, dass Encore.ts im Vergleich zu Express.js einen neunfachen Anforderungsdurchsatz und im Vergleich zu Fastify einen zweifachen Anforderungsdurchsatz erreicht.

Heute setzen wir unsere Leistungsreise fort, indem wir untersuchen, wie Encore.ts unglaublich schnelle Kaltstart-Startzeiten erreicht.

Leistungsbenchmarks

Dieses Mal haben wir Encore.ts, Fastify, NestJS und Express verglichen, um zu sehen, wie jedes Framework in Bezug auf Kaltstartzeiten abschneidet.

Das Benchmark-Programm registriert 10 API-Endpunkte mit jeweils einem einfachen Schema und richtet die Schemavalidierung ein.
Für die Schemavalidierung haben wir, wo möglich, Zod verwendet.
Im Fall von Fastify haben wir Ajv als offiziell unterstützte Schemavalidierungsbibliothek verwendet.

Wir haben die Zeit vom Beginn der Ausführung des JavaScript-Codes bis zur Bereitschaft des Servers zur Annahme eingehender Anfragen gemessen.
Für jeden Benchmark haben wir das beste Ergebnis aus fünf Läufen erzielt.

Genug geredet, schauen wir uns die Zahlen an!

Die Kaltstarts von Encore.ts sind 17x schneller als NestJS und Fastify

Encore.ts —  Faster cold starts than NestJS & Fastify

(Schauen Sie sich den Benchmark-Code auf GitHub an.)

Wie Sie sehen können, Encore.ts erreicht bemerkenswert schnelle Kaltstartzeiten, über 5x schneller als Express und über 17x schneller als NestJS.

Wie ist das möglich? Bei unseren Tests haben wir zwei Hauptquellen für die Leistung identifiziert, die beide damit zusammenhängen, wie Encore.ts unter der Haube funktioniert.

Aber bevor wir dort ankommen, sprechen wir darüber, was Kaltstarts wirklich sind und warum sie wichtig sind.

Was ist ein Kaltstart?

Im serverlosen Kontext liegt ein Kaltstart vor, wenn die zugrunde liegende Plattform zunächst eine neue Instanz Ihres Servers hochfahren muss, um eine eingehende Anfrage zu bedienen. (Es kann sich auch auf das erste Mal beziehen, dass eine neue Instanz Ihres Servers gestartet wird, um eine Anfrage zu bearbeiten, beispielsweise nach einer Bereitstellung.)

Da die Anfrage praktisch in der Warteschleife bleibt, bis der Prozess startet und zur Bearbeitung der Anfrage bereit ist, kann die Reduzierung der Kaltstartzeiten große Auswirkungen auf die Long-Tail-Latenz Ihrer Anwendung haben.

Dies ist besonders wichtig für verteilte Systeme, in denen Sie über mehrere serverlose Funktionen verfügen, da es viel wahrscheinlicher ist, dass es bei der Bearbeitung einer Anfrage zu einem Kaltstart in einem Teil des Systems kommt.

Die Anatomie eines Kaltstarts

Was genau bei einem Kaltstart passiert, hängt ein wenig von der Plattform ab, auf der Sie die Bereitstellung durchführen (Kubernetes, Lambda, Cloud Run usw.).
Aber im Allgemeinen sieht der Prozess ungefähr so ​​aus:

  1. Plattform lädt das Code-/Container-Image für die serverlose Funktion herunter
  2. Plattform startet eine neue Instanz des Containers/der serverlosen Funktion/des Containers
  3. Der Container/die Funktion initialisiert sich selbst (JavaScript-Module importieren, Ausführen des Initialisierungscodes usw.)

Nach diesen Initialisierungsschritten ist der Kaltstart abgeschlossen und die serverlose Funktion beginnt mit der Verarbeitung der eingehenden Anfrage.

Die ersten beiden Schritte liegen größtenteils außerhalb unserer Kontrolle (außer sicherzustellen, dass die Größe des Codes/Containers optimiert ist), also richten wir unsere Aufmerksamkeit auf den dritten Schritt.

Lassen Sie uns den dritten Schritt genauer aufschlüsseln und davon ausgehen, dass wir Node.js ausführen:

  1. Der Knotenprozess startet und beginnt mit der Initialisierung der V8-JavaScript-Engine
  2. Die Einstiegspunktdatei wird analysiert, geladen und beginnt mit der Ausführung des Anwendungscodes
  3. Wenn der JavaScript-Code Import- und Require-Anweisungen ausführt, werden noch mehr Dateien geladen, analysiert und ausgeführt. (Bei Anwendungen mit vielen Abhängigkeiten mehrmals wiederholen.)

Nachdem alle Abhängigkeiten geladen und der gesamte Initialisierungscode ausgeführt wurde, ist die Container-/Serverless-Funktion schließlich bereit, eingehende Anfragen zu verarbeiten.

Kaltstarts optimieren

Die obige Aufschlüsselung gibt uns klare Ziele für die Optimierung, und Encore.ts optimiert alle Schritte, über die es die Kontrolle hat, stark.

Optimierung 1: Rust-Laufzeit

Encore.ts wird in Rust implementiert und als natives Modul in Node.JS geladen. Dies hat beim Kaltstart mehrere Vorteile:

Weniger JavaScript zum Parsen und Ausführen. Da JavaScript eine interpretierte Sprache ist, muss der gesamte JavaScript-Code von der Festplatte gelesen, analysiert und ausgeführt werden. Encore.ts lädt als vorkompiliertes natives Modul extrem schnell und muss nicht von der JavaScript-Engine (V8) analysiert oder ausgeführt werden.

Keine NPM-Abhängigkeiten. Da Encore.ts seine gesamte Funktionalität mit Rust implementiert, gibt es keinerlei NPM-Abhängigkeiten, was die Menge an JavaScript, die bei einem Kaltstart ausgeführt werden muss, weiter reduziert.

Vorkompiliert und optimiert. JavaScript basiert stark auf der Just-in-Time-Kompilierung (JIT), bei der Code, der wiederholt ausgeführt wird, von der JavaScript-Engine optimiert wird. Dies ist für eine interpretierte Sprache sehr sinnvoll, bedeutet aber auch, dass die Ausführung beim ersten Ausführen eines Codeabschnitts deutlich langsamer ist, was sich erheblich auf Kaltstarts auswirkt. Da Encore.ts in Rust implementiert ist, ist es vorkompiliert und stark für die Plattform optimiert, auf der es läuft, was bedeutet, dass es von der ersten Ausführung an schnell ist.

Optimierung 2: Effiziente Docker-Images

Encore.ts erstellt standardmäßig minimierte Docker-Images, indem es nur transpiliertes JavaScript und die notwendigen Abhängigkeiten zum Ausführen der Anwendung einbezieht. Dies reduziert die Bundle-Größen, was wiederum die Zeit verkürzt, die zum Herunterladen und Starten des Containers benötigt wird.

Darüber hinaus haben mehrere Computerplattformen Unterstützung für das Streaming von Docker-Images hinzugefügt, was bedeutet, dass die Plattform den Container starten kann, bevor das gesamte Image heruntergeladen wurde. Encore.ts verfügt hierfür über eine integrierte Unterstützung und priorisiert automatisch die Teile des Bildes, die benötigt werden, um Kaltstarts zu reduzieren.

Einpacken

Durch die Kombination einer Rust-Laufzeit mit optimierten Docker-Images ist Encore.ts in der Lage, bemerkenswerte Kaltstartzeiten zu erreichen, die einen großen Einfluss auf die Long-Tail-Latenz Ihrer Anwendung haben können.

Wenn die Leistung für Ihr Projekt wichtig ist, ist es möglicherweise eine gute Idee, Encore.ts auszuprobieren.

Und es ist alles Open Source, sodass Sie sich den Code ansehen und auf GitHub beitragen können.

Oder probieren Sie es einfach aus und teilen Sie uns Ihre Meinung mit!

Das obige ist der detaillierte Inhalt vonEncore.ts – Schnellere Kaltstarts als NestJS und Fastify. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn