Как обнаружить и измерить блокировку цикла событий в 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);
});

Распечатает, как долго в мс цикл событий блокируется для