
Исходный код бенчмарка (вариант №1):
var Promise = require('bluebird'); // Если хотите проверить скорость работы нативных промисов то необходимо закомментировать данную строку.
var crypto = require('crypto');
var iterations = 1000000;
var start = Date.now();
var arrayPromises = [];
var promiseWrap = function () {
return new Promise(function (resolve, reject) {
crypto.randomBytes(256, (err, buf) => {
if (err) reject(err);
resolve(buf);
});
});
};
for(var i = 0; i < iterations; i++){
arrayPromises.push(promiseWrap());
}
if(arrayPromises.length === iterations){
Promise.all(arrayPromises).then(function (result) {
var finish = Date.now()-start;
console.log("Бенчмарк промисов выполнен!");
console.log("Время выполнения "+finish/1000+" сек.");
});
}
Исходный код бенчмарка (вариант №2):
var Promise = require('bluebird'); // Если хотите проверить скорость работы нативных промисов то необходимо закомментировать данную строку.
var crypto = require('crypto');
var iterations = 1000000;
var start = Date.now();
var arrayPromises = [];
var promiseWrap = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(Math.random(1));
},0)
});
};
for(var i = 0; i < iterations; i++){
arrayPromises.push(promiseWrap());
}
if(arrayPromises.length === iterations){
Promise.all(arrayPromises).then(function (result) {
var finish = Date.now()-start;
console.log("Бенчмарк промисов выполнен!");
console.log("Время выполнения "+finish/1000+" сек.");
});
}
Данный бенчмарк в качестве результата выводит время, за которое резолвятся все промисы. Результаты бенчмарка на моей машине:
Время выполнения:
Нативные промисы (вариант №1 node v6.4.0) — 19.808 сек.
Bluebird-промисы (вариант №1 node v6.4.0) — 9.654 сек.
Нативные промисы (вариант №1 node v6.5.0) — 19.957 сек.
Bluebird-промисы (вариант №1 node v6.5.0) — 9.723 сек.
Нативные промисы (вариант №2 node v6.5.0) — 10.61 сек.
Bluebird-промисы (вариант №2 node v6.5.0) — 2.208 сек.
Максимальное значение выделенной памяти (rss):
Нативные промисы (вариант №2 node v6.5.0) — 1282 Мб.
Bluebird-промисы (вариант №2 node v6.5.0) — 601 Мб.
Среднее значение выделенной памяти (rss):
Нативные промисы (вариант №2 node v6.5.0) — 368 Мб.
Bluebird-промисы (вариант №2 node v6.5.0) — 297 Мб.
Вывод: bluebird промисы работают быстрее нативных промисов в 2-5 раз, а так же требуют гораздо меньше оперативной памяти.
Если я в чем то ошибаюсь, то большая просьба сообщить в комментариях. Буду очень рад услышать от вас, какие либо поправки.
» Ссылка на библиотеку bluebird
Комментарии (27)

neoxack
31.08.2016 17:20+2Абсолютно бесполезный бенчмарк. Тестировать промисы нужно под асинхронной нагрузкой.
Iqorek
31.08.2016 23:07Что даст «асинхронная нагрузка»? Завалит callback queue колбеками от асинхронных вызовов? На чистое время исполнения промисов, это не повлияет.

igontarev
31.08.2016 17:20впечатляет, а что на счет observble?
Iqorek
31.08.2016 23:08-2Object.observe? судя по всему он тоже написан на javascript и там тоже можно ожидать худших результатов, чем у аналогов.

SDI
31.08.2016 17:40Неделю назад был статья JavaScript Performance, базы данных и поиски «серебряной пули»: видеозаписи ТОП-5 докладов HolyJS 2016
В ней есть видео на доклад Вячеслава Егорова, «Производительность JavaScript через подзорную трубу»
В данном докладе объясняется почему данный бенчмарк некорректен.
И вот хорошая статься Что браузеры делают с вашим JavaScript-кодом: об оптимизациях в JS-движках на примере V8
Laney1
31.08.2016 18:10+5рискну предположить, что разработчики v8 не стараются оптимизировать промисы, потому что для них это не критично. Какая разница, сколько миллисекунд будет потрачено в служебном коде, если в 99.5% случаев промису придется ждать ответ на веб-запрос? Но разработчику bluebird все равно респект

jMas
31.08.2016 19:37+1Иногда промисы используют например в анимациях:
function show(element) { return new Promise(resolve => element.animate([ { opacity: 0, transform: 'scale(.5)' }, { opacity: 1, transform: 'scale(1)' } ], { duration: 250 }).onfinish = resolve).then(() => { element.style.opacity = 1; }); }
vintage
31.08.2016 20:28+1В собственно анимации тут промисы явно не используются.

jMas
31.08.2016 21:47Более — они и в Ajax запросах, в популярных библиотеках, тоже явно не используются. Я просто привел пример, где производительность промисов может как то повлиять на конечный результат.

vintage
31.08.2016 23:31В данном случае один единственный промис не в состоянии как-либо повлиять на анимацию.

jMas
01.09.2016 11:32+1show(el).then(() => hide(el)).then(() => show(el)).then(() => expand(el))...;
Например цепочка промисов. Чем больше задержка в промисах, тем дерганей будут переходы между анимациями. Но да, полагаю это не сильно существенно если промисы достаточно быстрые и доли секунды не заметны глазу.
Но не всегда асинхонная функция асинхронна. Иногда функция (в зависимости от разных ситуаций) сама принемает решение: получить данные из стороннего источника или взять уже имеющиеся в кэше и отдать синхронно, но интерфейс все равно — промис. Тогда было бы не плохо получить данные максимально быстро. Не так ли?

Shannon
31.08.2016 20:18Стараются, по крайней мере движение есть
node v6.3.1: 26.3 сек
node v6.5.0: 16.5 сек
Вообще на node 6.5.0 тест из статьи выдает такие результаты:
Bluebird Время выполнения 14.876 сек. Native promise Время выполнения 16.519 сек.
ruslangavrilov
01.09.2016 07:40Странные результаты. У меня на node 6.5.0 совсем по другому. В статью добавил результаты, полученные при использовании этой версии.

Shannon
02.09.2016 03:55Первый вариант повторно
$ node prom.js Бенчмарк промисов выполнен! Время выполнения 14.426 сек. $ node prom.js Бенчмарк промисов выполнен! Время выполнения 15.856 сек. $ node -v v6.5.0
Второй вариант:
$ node prom.js Бенчмарк промисов выполнен! Время выполнения 2.7 сек. $ node prom.js Бенчмарк промисов выполнен! Время выполнения 10.404 сек.

vvadzim
31.08.2016 20:33Так это не сюрприз для активных промисеров :) На сайте блюберда: http://bluebirdjs.com/docs/benchmarks.html

Jabher
01.09.2016 00:13Все корректно — Петька Антонов адово крутит перфоманс, и его реализация давным-давно известна за чудовищную эффективность. А вот почему его код не перенесли в v8 — для меня большой вопрос.

hell0w0rd
01.09.2016 01:03bluebird быстрее стандартных промисов, да и прочих реализаций промисов. Это факт.
Но ваш тест, даже откинув остальные косяки, тестирует не промисы, аcrypto.randomBytes. То, что происходит внутри промисов должно выполняться за константное время, чтобы протестировать непосредственно промисы.

Andropolon
01.09.2016 07:37+1Рекомендую еще сравнить расход оперативной памяти на промисы.
Будете очень удивлены, особенно в Google Chrome.
По нашим тестам, нативные промисы съели около 200 МБайт памяти на 100 000 вызовов.
Bluebird — что-то около 10 Мбайт кажется.
kir_vesp
Про то как V8 оптмизирует код почитайте. Ваш бенчмарк совершенно некорректен.
ruslangavrilov
Спасибо за комментарий. Напишите, пожалуйста корректный бенчмарк. Очень хочется посмотреть на грамотную реализацию.
kir_vesp
Минимально корректным будет бэнчмарк, в котором Вы в каждый промис передавали бы новую переменнную, для примера можно глянуть на бэнчмарки в репозитории.
youlose
Зря накинулись:
http://programmers.stackexchange.com/questions/278778/why-are-native-es6-promises-slower-and-more-memory-intensive-than-bluebird
kir_vesp
За ссылку спасибо, аргументация хорошая. Убеждает.