В этом тесте комплекту обещаний ES6 требуется в 4 раза больше времени, чем обещаниям Bluebird, и он использует в 3,6 раза больше памяти.
Как библиотека JavaScript может быть намного быстрее и легче, чем собственная реализация v8, написанная на C? У обещаний Bluebird точно такой же API, как у обещаний ES6 (плюс куча дополнительных служебных методов).
Является ли нативная реализация просто плохо написанной, или есть какой-то другой аспект, который я упускаю?
javascript
performance
io.js
Каллум
источник
источник
new
оператором, потому что PromiseMeSpeedJS не используетnew
.Ответы:
Автор Bluebird здесь.
Реализация обещаний V8 написана на JavaScript, а не на C. Весь JavaScript (включая собственный V8) скомпилирован в нативный код. Кроме того, написанный пользователем JavaScript оптимизируется, если это возможно (и того стоит), перед компиляцией в собственный код. Реализация обещаний - это то, что не принесет особой пользы от написания на C, а на самом деле только замедлит ее, потому что все, что вы делаете - это манипулируете объектами JavaScript и связью.
Реализация V8 просто не так оптимизирована, как bluebird, она для экземпляров выделяет массивы для обработчиков обещаний . Это занимает много памяти, когда каждому обещанию также приходится выделять пару массивов (эталонный тест создает в целом 80 000 обещаний, так что выделяется 160 000 неиспользуемых массивов). В действительности, 99,99% вариантов использования никогда не выполняют обещание более одного раза, поэтому оптимизация для этого общего случая дает значительные улучшения в использовании памяти.
Даже если V8 реализует те же оптимизации, что и bluebird, это все равно будет затруднено спецификацией. Тест должен использовать
new Promise
(анти-паттерн в bluebird), так как в ES6 нет другого способа создать рутинное обещание.new Promise
это чрезвычайно медленный способ создания обещания, во-первых, функция executor выделяет замыкание, во-вторых, в качестве аргументов передается 2 отдельных замыкания. На каждое обещание выделяется 3 замыкания, но замыкание уже является более дорогим объектом, чем оптимизированное обещание.Можно использовать Bluebird,
promisify
которая позволяет выполнять множество оптимизаций и является гораздо более удобным способом использования API-интерфейсов обратного вызова, а также позволяет преобразовывать целые модули в модули на основе обещаний в одну строку (promisifyAll(require('redis'));
).источник
new Promise
или улучшения его создания, чтобы сделать его менее дорогим (например, не создавать 3 замыкания на экземпляр)?Promise.resolve()
для создания "root обещание"?Promise.resolve()
или чего-то еще), но это очень простая реализация, и ее существование не должно отталкивать вас от использования более серьезных инструментов, связанных с обещаниями, таких как bluebird!