Dans cet exemple , la suite prend 4 fois plus de temps avec les promesses ES6 par rapport aux promesses de Bluebird et utilise 3,6 fois plus de mémoire.
Comment une bibliothèque JavaScript peut-elle être tellement plus rapide et plus légère que l'implémentation native de v8 écrite en C? Les promesses Bluebird ont exactement la même API que les promesses natives ES6 (plus un tas de méthodes utilitaires supplémentaires).
L'implémentation native est-elle simplement mal écrite ou y a-t-il un autre aspect qui me manque?
javascript
performance
io.js
callum
la source
la source
new
opérateur parce que PromiseMeSpeedJS ne l'utilise pasnew
.Réponses:
Bluebird auteur ici.
L'implémentation des promesses V8 est écrite en JavaScript et non en C. Tout le JavaScript (y compris le propre de V8) est compilé en code natif. De plus, le code JavaScript écrit par l'utilisateur est optimisé, si possible (et vaut la peine), avant d'être compilé en code natif. La mise en œuvre des promesses ne bénéficierait pas beaucoup ou pas du tout d’être écrite en C, elle ne le ralentirait en fait que parce que tout ce que vous faites est de manipuler des objets JavaScript et de communiquer.
L'implémentation V8 n'est tout simplement pas aussi optimisée que bluebird, elle alloue des instances pour les gestionnaires de promesses . Cela prend beaucoup de mémoire lorsque chaque promesse doit également allouer deux tableaux (le point de référence crée des promesses globales de 80 000 donc 160 000 tableaux inutilisés alloués). En réalité, 99,99% des cas d'utilisation ne s'emboîtent jamais plus d'une fois dans la promesse. L'optimisation de ce cas courant permet ainsi d'améliorer considérablement l'utilisation de la mémoire.
Même si V8 implémentait les mêmes optimisations que bluebird, la spécification l’empêcherait. Le benchmark doit être utilisé
new Promise
(un anti-motif dans bluebird) car il n’ya pas d’autre moyen de créer une promesse fondamentale dans ES6.new Promise
est une manière extrêmement lente de créer une promesse, d’abord la fonction exécuteur alloue une fermeture, d’autre part, 2 fermetures séparées lui sont transmises comme arguments. C'est 3 fermetures allouées par promesse, mais une fermeture est déjà un objet plus coûteux qu'une promesse optimisée.Bluebird peut utiliser
promisify
ce qui permet de nombreuses optimisations et constitue un moyen beaucoup plus pratique de consommer des API de rappel et permet la conversion de modules entiers en modules à base de promesses en une seule ligne (promisifyAll(require('redis'));
).la source
new Promise
ou d’améliorer l’instanciation pour la rendre moins coûteuse (comme ne pas créer 3 fermetures par instance)?Promise.resolve()
pour créer une "promesse racine"?Promise.resolve()
ou quoi que ce soit), mais c'est une implémentation très basique, et son existence ne devrait pas vous décourager d'utiliser des outils plus sérieux liés aux promesses comme bluebird!