Как обнаружить и измерить блокировку цикла событий в node.js?
Я хочу отслеживать, как долго выполняется каждый цикл цикла в node.js. Однако я не уверен в лучшем способе измерения этого. Лучший способ, которым я мог придумать, выглядит так:
var interval = 500;
var interval = setInterval(function() {
var last = Date.now();
setImmediate(function() {
var delta = Date.now() - last;
if (delta > blockDelta) {
report("node.eventloop_blocked", delta);
}
});
}, interval);
Я в основном выводю время цикла цикла событий, посмотрев на задержку setInterval
. Я видел такой же подход в модуле blocked node, но он чувствует себя неточным и тяжелым. Есть ли лучший способ получить эту информацию?
Обновление: Изменен код для использования setImmediate
, как это сделано hapi.js.
Ответы
Ответ 1
"Есть ли лучший способ получить эту информацию?"
У меня нет лучшего способа протестировать eventloop, чем проверка временной задержки SetImmediate, но вы можете получить более высокую точность, используя node таймер с высоким разрешением вместо Date.now()
var interval = 500;
var interval = setInterval(function() {
var last = process.hrtime(); // replace Date.now()
setImmediate(function() {
var delta = process.hrtime(last); // with process.hrtime()
if (delta > blockDelta) {
report("node.eventloop_blocked", delta);
}
});
}, interval);
ПРИМЕЧАНИЕ: delta будет массивом кортежей [секунды, наносекунды].
Подробнее о process.hrtime():
https://nodejs.org/api/all.html#all_process_hrtime
"Основное использование - измерение производительности между интервалами".
Ответ 2
Код
этот код будет измерять время в наносекундах, которое требуется для запуска цикла событий. он измеряет время между текущим процессом и следующим тиком.
var time = process.hrtime();
process.nextTick(function() {
var diff = process.hrtime(time);
console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);
// benchmark took 1000000527 nanoseconds
});
EDIT: добавлено объяснение,
process.hrtime([время])
Возвращает текущее реальное время высокого разрешения в массиве [секунд, наносекунд]. time является необязательным параметром, который должен быть результатом предыдущего вызова process.hrtime() (и, следовательно, реального времени в массиве [секунд, наносекунд], содержащем предыдущее время) для разницы с текущим временем. Эти времена относятся к произвольному времени в прошлом и не относятся к времени суток и, следовательно, не подвержены часовому дрейфу. Основное использование - измерение производительности между интервалами.
process.nextTick(callback [, arg] [,...])
Как только цикл цикла текущего события завершится, вызовите функцию обратного вызова.
Это не простой псевдоним setTimeout (fn, 0), он намного эффективнее. Он запускается до того, как любые последующие события ввода-вывода (включая таймеры) срабатывают при последующих тиках цикла событий.
Ответ 3
Проверьте этот плагин https://github.com/tj/node-blocked Я использую его сейчас, и он, кажется, делает то, что вы хотите.
let blocked = require("blocked");
blocked(ms => {
console.log("EVENT LOOP Blocked", ms);
});
Распечатает, как долго в мс цикл событий блокируется для
Ответ 4
Вы также можете посмотреть профилирование, встроенное в node
и io.js
. См., Например, эту статью http://www.brendangregg.com/flamegraphs.html
И этот связанный ответ SO Отладка Node.js приложений