Чому рідний ES6 обіцяє повільніше та більш пам’яті, ніж синій птах?


195

У цьому орієнтирі пакет займає у 4 рази більше часу, щоб виконати обіцянки ES6 порівняно з обіцянками Bluebird, і використовує в 3,6 рази більше пам’яті.

Як бібліотека JavaScript може бути настільки швидшою і легшою, ніж вбудована версія v8, написана на C? Bluebird обіцянки мають точно такий же API, як і рідні ES6 обіцянки (плюс купа додаткових корисних методів).

Чи вроджена реалізація просто погано написана, чи є якийсь інший аспект до цього, який мені не вистачає?


Майте на увазі, що сучасні реалізації JavaScript сильно оптимізовані та можуть навіть працювати за допомогою JIT .

1
Згідно з цим еталоном , BlueBirdJS насправді повільніше, ніж Native Promises. Але PromiseMeSpeedJS насправді перевершує їх обох. Однією з багатьох речей, які PromiseMeSpeedJS доводить через це, є те, що головним винуватцем виконання обіцянок є жорстоке використання newоператора, оскільки PromiseMeSpeedJS не використовує new.
Джек Гіффін

1
@JackGiffin Chrome 67: PromiseMeSpeedJS повільніше на 46%, а Bluebird - на 61% повільніше.
FINDarkside

Відповіді:


272

Автор блакитної птиці тут.

Реалізація обіцянок V8 написана на JavaScript, а не C. Весь JavaScript (у тому числі власний V8) складений у рідний код. Додатково написаний користувачем JavaScript оптимізується, якщо можливо (і варто того), перед тим, як компілювати до рідного коду. Обіцяє реалізація - це те, що не писало б великої або взагалі користі від написання на C, адже це зробило б лише повільніше, оскільки все, що ви робите, - це маніпулювання об'єктами JavaScript та спілкування.

Реалізація V8 просто не настільки оптимізована, як bluebird, вона для примірників виділяє масиви для обробників обіцянок . Це займає багато пам’яті, коли кожна обіцянка також повинна виділити пару масивів (Орієнтир створює загальні 80-кілограмові обіцянки, так що виділено 160 000 невикористаних масивів). Насправді 99,99% випадків використання ніколи не виконують обіцянки не раз, тому оптимізація для цього звичайного випадку отримує величезні покращення використання пам'яті.

Навіть якби V8 здійснив ті ж оптимізації, що і синій птах, це все-таки заважатиме специфікації. Базовий показник повинен використовувати new Promise(анти-візерунок у блакитного птаха), оскільки немає іншого способу створити кореневу обіцянку в ES6. new Promiseце надзвичайно повільний спосіб створення обіцянки, по-перше функція виконавця виділяє закриття, по-друге йому передаються 2 окремих закриття як аргументи. Це 3 закриття, виділені на обіцянку, але закриття - це вже більш дорогий об'єкт, ніж оптимізована обіцянка.

Bluebird може використовувати, promisifyщо дозволяє безліч оптимізацій і є набагато зручнішим способом використання API зворотного виклику, і це дозволяє конвертувати цілі модулі в модулі, засновані на обіцянках, в одному рядку ( promisifyAll(require('redis'));).


10
"все ще заважає специфікація" - Не впевнений, що це означає. Ви хочете сказати, що ES6 слідує за специфікацією, яка за своєю суттю повільна, і якщо це так, чи означає це, що синя пташка не йде за тією ж специфікацією (і якщо це так, чи йде вона за іншою, а яка з них)? І чи є якась причина, чому ES6 не міг би мати кращого способу створення кореневої обіцянки окрім new Promiseабо покращити інстанціювання, щоб зробити її дешевшою (як, наприклад, не створюючи 3 закриття на примірник)?
Ентоні

12
Це зовсім не добре (для JS). Я дійсно не хочу використовувати бібліотеку Promise, коли є внутрішня реалізація. Це більш ніж невдала ситуація для всіх, якщо це все правда. Але у мене вже є проблеми з переглядом Promise-hype, я написав 100 000 програм LoC JS, і досі не бачу ніякої реальної потреби в цьому, це дуже незначне поліпшення, якщо взагалі для мене , в основному в роботі з помилками, ні вдосконалення керування зворотними дзвінками (я ніколи не був у "пеклі зворотного дзвінка" зі своїм стилем кодування).
Мерре

19
У ES6 ви не можете Promise.resolve()створити "кореневу обіцянку"?
zetlen

10
@ MörreNoseshine (продовження) Роками пізніше автори ES6 підійшли і сказали: "Ей, давайте уточнимо, що двигуни JS повинні надавати загальні обіцянки / A + відповідні утиліти поза коробкою, тому люди завжди мають основний інструмент для обіцянок на руку" ". Це приємна зручність (не потрібно імпортувати бібліотеку просто для швидкого Promise.resolve()чи будь-якого іншого), але це дуже основна реалізація, і її існування не повинно відштовхувати вас від використання більш серйозних інструментів, пов'язаних з обіцянками, як bluebird!
callum

11
@ MörreNoseshine 100k LOC Додаток Javascript, який, ймовірно, ніколи не мав функцій асинхронізації. Удачі, написавши 100k LoC JS гру з бібліотекою mysql / redis без bluebird.
NiCk Newman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.