Исходный код бенчмарка (вариант №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
За ссылку спасибо, аргументация хорошая. Убеждает.