In diesem Benchmark benötigt die Suite bei ES6-Versprechungen 4-mal mehr Zeit als bei Bluebird-Versprechungen und benötigt 3,6-mal mehr Speicher.
Wie kann eine JavaScript-Bibliothek so viel schneller und leichter sein als die native Implementierung von v8 in C? Bluebird-Versprechen haben genau die gleiche API wie native ES6-Versprechen (plus eine Reihe zusätzlicher Dienstprogrammmethoden).
Ist die native Implementierung nur schlecht geschrieben, oder fehlt mir noch ein anderer Aspekt?
javascript
performance
io.js
Callum
quelle
quelle
new
Betreibers ist, da PromiseMeSpeedJS nicht verwendetnew
.Antworten:
Bluebird-Autor hier.
Die Implementierung von V8 verspricht, dass sie in JavaScript und nicht in C geschrieben ist . Jegliches JavaScript (einschließlich des eigenen V8) wird zu nativem Code kompiliert. Zusätzlich wird benutzergeschriebenes JavaScript nach Möglichkeit (und im Wert) optimiert, bevor es zu nativem Code kompiliert wird. Die Implementierung von Versprechungen ist etwas, das nicht viel oder gar nichts davon hat, in C geschrieben zu werden. Tatsächlich würde es nur langsamer, da Sie lediglich JavaScript-Objekte und die Kommunikation manipulieren.
Die V8-Implementierung ist einfach nicht so optimiert wie Bluebird, sondern ordnet Arrays für die Handler von Versprechungen zu . Dies nimmt viel Speicherplatz in Anspruch, wenn jedes Versprechen auch ein paar Arrays zuweisen muss (Der Benchmark erstellt insgesamt 80.000 Versprechen, sodass 160.000 nicht verwendete Arrays zugewiesen werden). In der Realität geben 99,99% der Anwendungsfälle niemals ein Versprechen mehr als einmal ab, sodass die Optimierung für diesen allgemeinen Fall enorme Verbesserungen der Speichernutzung mit sich bringt.
Selbst wenn V8 dieselben Optimierungen wie Bluebird implementieren würde, würde dies durch die Spezifikation behindert. Der Benchmark muss
new Promise
(ein Anti-Pattern in Bluebird) verwenden, da es in ES6 keine andere Möglichkeit gibt, ein Root-Versprechen zu erstellen.new Promise
ist ein extrem langsamer Weg, um ein Versprechen zu erstellen. Erstens weist die Executor-Funktion einen Abschluss zu, zweitens werden zwei separate Abschlüsse als Argumente übergeben. Das sind 3 Verschlüsse pro Versprechen, aber ein Verschluss ist bereits ein teureres Objekt als ein optimiertes Versprechen.Bluebird kann verwenden,
promisify
was viele Optimierungen ermöglicht und eine viel bequemere Möglichkeit darstellt, Callback-APIs zu nutzen, und es ermöglicht die Konvertierung ganzer Module in versprechungsbasierte Module in einer Zeile (promisifyAll(require('redis'));
).quelle
new Promise
in der Lage sein könnte, ein Root-Promise zu erstellen oder die Instantiierung zu verbessern, um es kostengünstiger zu machen (z. B. keine drei Abschlüsse pro Instanz zu erstellen)?Promise.resolve()
"Root-Versprechen" erstellen?Promise.resolve()
oder was auch immer zu tun ), aber es ist eine sehr einfache Implementierung, und ihre Existenz sollte Sie nicht davon abhalten, ernsthaftere versprechungsbezogene Tools wie Bluebird zu verwenden!