Spec-Zone.ru › Node.js 12 LTS

API для измерения производительности

Устойчивость: 2 - Стабильно

Исходный код: lib/perf_hooks.js

Этот модуль предоставляет реализацию подмножества API W3C Web Performance APIs, а также дополнительные API для измерений производительности, специфичных для Node.js.

Node.js поддерживает следующие API веб-производительности:

  • Высокоточная замер времени
  • Временная шкала производительности
  • Измерение времени работы пользователя
const { PerformanceObserver, performance } = require('perf_hooks');

const obs = new PerformanceObserver((items) => {
  console.log(items.getEntries()[0].duration);
  performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });
performance.measure('Start to Now');

performance.mark('A');
doSomeLongRunningProcess(() => {
  performance.measure('A to Now', 'A');

  performance.mark('B');
  performance.measure('A to B', 'A', 'B');
});

perf_hooks.performance

Добавлена в: v8.5.0

Объект, который можно использовать для сбора метрик производительности текущего экземпляра Node.js. Он похож на window.performance в браузерах.

performance.clearMarks([name])

Добавлена в: v8.5.0
  • name <строка>

Если name не указан, удаляет все PerformanceMark объекты из временной шкалы производительности. Если name указан, удаляет только отметку с указанным именем.

performance.eventLoopUtilization([utilization1[, utilization2]])

Добавлена в: v14.10.0, v12.19.0
  • utilization1 <объект> Результат предыдущего вызова eventLoopUtilization().
  • utilization2 <объект> Результат предыдущего вызова eventLoopUtilization() до utilization1.
  • Возвращает <объект>
    • idle <число>
    • active <число>
    • utilization <число>

Метод eventLoopUtilization() возвращает объект, содержащий суммарное время, которое цикл событий был как в состоянии ожидания, так и в активном состоянии, как высокоточные миллисекунды. Значение utilization — это вычисленная загрузка цикла событий (ELU).

Если загрузка главного потока еще не завершена, свойства имеют значение 0. ELU немедленно доступен в потоках-работниках, так как загрузка происходит внутри цикла событий.

И utilization1, и utilization2 являются необязательными параметрами.

Если utilization1 передаётся, то рассчитывается разность между текущим значением active и idle вызовов, а также соответствующее значение utilization (аналогично process.hrtime()).

Если utilization1 и utilization2 оба переданы, то разность рассчитывается между двумя аргументами. Это удобный вариант, поскольку, в отличие от process.hrtime(), вычисление ELU является более сложным, чем простое вычитание.

ELU похож на использование ЦП, за исключением того, что он измеряет только статистику цикла событий, а не использование ЦП. Он представляет собой процент времени, затраченного циклом событий вне поставщика событий цикла событий (например, epoll_wait). Никакое другое время простоя ЦП не учитывается. Вот пример того, как у почти неактивного процесса будет высокая ELU.

'use strict';
const { eventLoopUtilization } = require('perf_hooks').performance;
const { spawnSync } = require('child_process');

setImmediate(() => {
  const elu = eventLoopUtilization();
  spawnSync('sleep', ['5']);
  console.log(eventLoopUtilization(elu).utilization);
});

Хотя ЦП в основном простаивает при выполнении этого скрипта, значение utilization равно 1. Это связано с тем, что вызов child_process.spawnSync() блокирует цикл событий.

Передача пользовательского объекта вместо результата предыдущего вызова eventLoopUtilization() приведёт к неопределённому поведению. Значения возвращаемых данных не гарантируют отражение какого-либо корректного состояния цикла событий.

performance.mark([name])

Добавлена в: v8.5.0
  • name <строка>

Создаёт новую запись PerformanceMark во временной шкале производительности. PerformanceMark — подкласс PerformanceEntry, чей performanceEntry.entryType всегда 'mark', и чей performanceEntry.duration всегда 0. Отметки производительности используются для маркировки конкретных значимых моментов во временной шкале производительности.

performance.measure(name[, startMark[, endMark]])

История
Версия Изменения
v12.16.3

Параметры startMark и endMark стали необязательными.

v8.5.0

Добавлена в: v8.5.0

  • name <строка>
  • startMark <строка> Необязательно.
  • endMark <строка> Необязательно.

Создаёт новую запись PerformanceMeasure во временной шкале производительности. PerformanceMeasure — подкласс PerformanceEntry, чей performanceEntry.entryType всегда 'measure', и чей performanceEntry.duration измеряет число миллисекунд, прошедших с startMark и endMark.

Аргумент startMark может идентифицировать любой существующий PerformanceMark во временной шкале производительности или может идентифицировать любое из свойств временной метки, предоставляемых классом PerformanceNodeTiming. Если указанной startMark не существует, то startMark устанавливается в timeOrigin по умолчанию.

Необязательный аргумент endMark должен идентифицировать любой существующий PerformanceMark во временной шкале производительности или любое из свойств временной метки, предоставляемых классом PerformanceNodeTiming. endMark будет performance.now() если параметр не передан, в противном случае, если названный endMark не существует, будет выброшено исключение.

performance.nodeTiming

Добавлена в: v8.5.0
  • <PerformanceNodeTiming>

Это свойство является расширением Node.js. Оно недоступно в веб-браузерах.

Экземпляр класса PerformanceNodeTiming, предоставляющий метрики производительности для определённых этапов работы Node.js.

performance.now()

Добавлена в: v8.5.0
  • Возвращает: <число>

Возвращает текущую высокоточную временную метку в миллисекундах, где 0 соответствует началу текущего процесса node.

performance.timeOrigin

Добавлена в: v8.5.0
  • <число>

Значение timeOrigin определяет высокоточную временную метку в миллисекундах, с которой начался текущий процесс node, измеряемую в формате Unix time.

performance.timerify(fn)

Добавлена в: v8.5.0
  • fn <Функция>

Это свойство является расширением Node.js. Оно недоступно в веб-браузерах.

Оборачивает функцию в новую функцию, измеряющую время выполнения обернутой функции. Для доступа к данным о времени выполнения необходимо подписаться на событие 'function'.

const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

function someFunction() {
  console.log('hello world');
}

const wrapped = performance.timerify(someFunction);

const obs = new PerformanceObserver((list) => {
  console.log(list.getEntries()[0].duration);
  obs.disconnect();
});
obs.observe({ entryTypes: ['function'] });

// A performance timeline entry will be created
wrapped();

performance.eventLoopUtilization([util1][,util2])

Добавлена в: v12.19.0
  • util1 <объект> Результат предыдущего вызова eventLoopUtilization()
  • util2 <объект> Результат предыдущего вызова eventLoopUtilization() до util1
  • Возвращает <объект>
    • idle <число>
    • active <число>
    • utilization <число>

Метод eventLoopUtilization() возвращает объект, содержащий суммарное время, которое цикл событий был как в состоянии ожидания, так и в активном состоянии, как высокоточные миллисекунды. Значение utilization — это вычисленная загрузка цикла событий (ELU). Если загрузка ещё не завершена, свойства имеют значение 0.

util1 и util2 являются необязательными параметрами.

Если util1 передаётся, то рассчитывается разность между текущим значением active и idle вызовов и возвращается (аналогично process.hrtime()). Также рассчитывается скорректированное значение utilization.

Если util1 и util2 оба переданы, то корректировки вычислений производятся между двумя аргументами. Это удобный вариант, так как в отличие от process.hrtime() выполняется дополнительная работа по вычислению ELU.

ELU похож на использование процессора, но рассчитывается с использованием высокоточного времени реальных часов. Он представляет собой процент времени, который цикл событий потратил вне поставщика событий цикла событий (например, epoll_wait). Другое время простоя процессора не учитывается. Ниже приведен пример того, как у преимущественно неактивного процесса будет высокое значение ELU.

'use strict';
const { eventLoopUtilization } = require('perf_hooks').performance;
const { spawnSync } = require('child_process');

setImmediate(() => {
  const elu = eventLoopUtilization();
  spawnSync('sleep', ['5']);
  console.log(eventLoopUtilization(elu).utilization);
});

Несмотря на то, что процессор в основном простаивает во время выполнения этого скрипта, значение utilization равно 1. Это связано с тем, что вызов child_process.spawnSync() блокирует цикл событий.

Передача пользовательского объекта вместо результата предыдущего вызова eventLoopUtilization() приведет к неопределенному поведению. Значения возвращаемых данных не гарантируют отражения правильного состояния цикла событий.

Класс: PerformanceEntry

Добавлен в: v8.5.0

performanceEntry.duration

Добавлен в: v8.5.0
  • <число>

Общее количество миллисекунд, затраченное на эту запись. Это значение не будет иметь смысла для всех типов записей производительности.

performanceEntry.name

Добавлен в: v8.5.0
  • <строка>

Имя записи производительности.

performanceEntry.startTime

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, обозначающая начальное время записи производительности.

performanceEntry.entryType

Добавлен в: v8.5.0
  • <строка>

Тип записи производительности. Он может быть одним из:

  • 'node' (только Node.js)
  • 'mark' (доступно в браузере)
  • 'measure' (доступно в браузере)
  • 'gc' (только Node.js)
  • 'function' (только Node.js)
  • 'http2' (только Node.js)
  • 'http' (только Node.js)

performanceEntry.kind

Добавлен в: v8.5.0
  • <число>

Это свойство расширено Node.js. Оно недоступно в браузерах.

Когда performanceEntry.entryType равно 'gc', свойство performance.kind идентифицирует тип операции сборки мусора, которая произошла. Значение может быть одним из:

  • perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR
  • perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR
  • perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL
  • perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB

performanceEntry.flags

Добавлен в: v12.17.0
  • <число>

Это свойство расширено Node.js. Оно недоступно в браузерах.

Когда performanceEntry.entryType равно 'gc', свойство performance.flags содержит дополнительную информацию об операции сборки мусора. Значение может быть одним из:

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY
  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE

Класс: PerformanceNodeTiming extends PerformanceEntry

Добавлен в: v8.5.0

Это свойство расширено Node.js. Оно недоступно в браузерах.

Предоставляет данные о времени выполнения Node.js. Конструктор этого класса не доступен пользователям.

performanceNodeTiming.bootstrapComplete

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, когда процесс Node.js завершил загрузку. Если загрузка ещё не завершена, свойство имеет значение -1.

performanceNodeTiming.environment

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, когда была инициализирована среда Node.js.

performanceNodeTiming.loopExit

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, когда цикл событий Node.js завершился. Если цикл событий ещё не завершился, свойство имеет значение -1. Оно может иметь значение не равное -1 только в обработчике события 'exit'.

performanceNodeTiming.loopStart

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, когда был начат цикл событий Node.js. Если цикл событий ещё не начался (например, в первом цикле основного скрипта), свойство имеет значение -1.

performanceNodeTiming.nodeStart

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, когда был инициализирован процесс Node.js.

performanceNodeTiming.v8Start

Добавлен в: v8.5.0
  • <число>

Отметка времени в миллисекундах высокой точности, когда была инициализирована платформа V8.

performanceNodeTiming.idleTime

Добавлен в: v12.19.0
  • <число>

Отметка времени в миллисекундах высокой точности для времени простоя цикла событий внутри поставщика событий цикла событий (например, epoll_wait). Это не учитывает использование процессора. Если цикл событий ещё не начался (например, в первом цикле основного скрипта), свойство имеет значение 0.

Класс: perf_hooks.PerformanceObserver

new PerformanceObserver(callback)

Добавлен в: v8.5.0
  • callback <Функция>
    • list <PerformanceObserverEntryList>
    • observer <PerformanceObserver>

PerformanceObserver объекты предоставляют уведомления, когда новые PerformanceEntry экземпляры были добавлены в временную шкалу производительности.

const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

const obs = new PerformanceObserver((list, observer) => {
  console.log(list.getEntries());
  observer.disconnect();
});
obs.observe({ entryTypes: ['mark'], buffered: true });

performance.mark('test');

Поскольку экземпляры PerformanceObserver вводят свой дополнительный накладной расход производительности, экземпляры не должны постоянно подписываться на уведомления. Пользователи должны отключать наблюдатели, как только они больше не нужны.

callback вызывается, когда PerformanceObserver получает уведомление о новых PerformanceEntry экземплярах. Обработчик получает экземпляр PerformanceObserverEntryList и ссылку на PerformanceObserver.

performanceObserver.disconnect()

Добавлен в: v8.5.0

Отключает экземпляр PerformanceObserver от всех уведомлений.

performanceObserver.observe(options)

Добавлен в: v8.5.0
  • options <Объект>
    • entryTypes <массив строк> Массив строк, идентифицирующих типы PerformanceEntry экземпляров, которые интересуют наблюдатель. Если не указано, будет выброшено исключение.
    • buffered <логическое значение> Если true, обратный вызов уведомления будет вызван с помощью setImmediate() и несколько уведомлений экземпляров PerformanceEntry будут буферизованы внутри. Если false, уведомления будут мгновенными и синхронными. По умолчанию: false.

Подписывает экземпляр PerformanceObserver на уведомления о новых PerformanceEntry экземплярах, идентифицированных options.entryTypes.

Когда options.buffered равно false, callback будет вызываться один раз для каждого экземпляра PerformanceEntry:

const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

const obs = new PerformanceObserver((list, observer) => {
  // Called three times synchronously. `list` contains one item.
});
obs.observe({ entryTypes: ['mark'] });

for (let n = 0; n < 3; n++)
  performance.mark(`test${n}`);
const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

const obs = new PerformanceObserver((list, observer) => {
  // Called once. `list` contains three items.
});
obs.observe({ entryTypes: ['mark'], buffered: true });

for (let n = 0; n < 3; n++)
  performance.mark(`test${n}`);

Класс: PerformanceObserverEntryList

Добавлен в: v8.5.0

Класс PerformanceObserverEntryList используется для доступа к PerformanceEntry экземплярам, переданным PerformanceObserver. Конструктор этого класса не доступен пользователям.

performanceObserverEntryList.getEntries()

Добавлен в: v8.5.0
  • Возвращает: <массив PerformanceEntry>

Возвращает список PerformanceEntry объектов в хронологическом порядке по отношению к performanceEntry.startTime.

performanceObserverEntryList.getEntriesByName(name[, type])

Добавлен в: v8.5.0
  • name <string>
  • type <string>
  • Возвращает: <PerformanceEntry[]>

Возвращает список объектов PerformanceEntry в хронологическом порядке относительно performanceEntry.startTime, у которых performanceEntry.name равно name, и необязательно, у которых performanceEntry.entryType равно type.

performanceObserverEntryList.getEntriesByType(type)

Добавлен в: v8.5.0
  • type <string>
  • Возвращает: <PerformanceEntry[]>

Возвращает список объектов PerformanceEntry в хронологическом порядке относительно performanceEntry.startTime, у которых performanceEntry.entryType равно type.

perf_hooks.monitorEventLoopDelay([options])

Добавлен в: v11.10.0
  • options <Object>
    • resolution <number> Частота дискретизации в миллисекундах. Должно быть больше нуля. По умолчанию: 10.
  • Возвращает: <Histogram>

Это свойство является расширением Node.js. Оно недоступно в веб-браузерах.

Создает объект Histogram для отслеживания и отчётности о задержке цикла событий со временем. Задержки будут отчитываться в наносекундах.

Использование таймера для определения приблизительной задержки цикла событий работает, потому что выполнение таймеров тесно связано с жизненным циклом цикла событий libuv. То есть, задержка в цикле вызовет задержку в выполнении таймера, и именно эти задержки предназначены для обнаружения этим API.

const { monitorEventLoopDelay } = require('perf_hooks');
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
// Do something.
h.disable();
console.log(h.min);
console.log(h.max);
console.log(h.mean);
console.log(h.stddev);
console.log(h.percentiles);
console.log(h.percentile(50));
console.log(h.percentile(99));

Класс: Histogram

Добавлен в: v11.10.0

Отслеживает задержку цикла событий с заданной частотой дискретизации. Конструктор этого класса не доступен пользователям.

Это свойство является расширением Node.js. Оно недоступно в веб-браузерах.

histogram.disable()

Добавлен в: v11.10.0
  • Возвращает: <boolean>

Отключает таймер отбора проб задержки цикла событий. Возвращает true если таймер был остановлен, false если он уже был остановлен.

histogram.enable()

Добавлен в: v11.10.0
  • Возвращает: <boolean>

Включает таймер отбора проб задержки цикла событий. Возвращает true если таймер был запущен, false если он уже был запущен.

histogram.exceeds

Добавлен в: v11.10.0
  • <number>

Количество раз, когда задержка цикла событий превысила максимальный порог задержки цикла событий в 1 час.

histogram.max

Добавлен в: v11.10.0
  • <number>

Максимальная зарегистрированная задержка цикла событий.

histogram.mean

Добавлен в: v11.10.0
  • <number>

Среднее значение зарегистрированных задержек цикла событий.

histogram.min

Добавлен в: v11.10.0
  • <number>

Минимальная зарегистрированная задержка цикла событий.

histogram.percentile(percentile)

Добавлен в: v11.10.0
  • percentile <number> Значение процентиля от 1 до 100.
  • Возвращает: <number>

Возвращает значение в заданном процентиле.

histogram.percentiles

Добавлен в: v11.10.0
  • <Map>

Возвращает объект Map с подробной информацией о накопленном распределении процентилей.

histogram.reset()

Добавлен в: v11.10.0

Сбрасывает собранные данные гистограммы.

histogram.stddev

Добавлен в: v11.10.0
  • <number>

Стандартное отклонение зарегистрированных задержек цикла событий.

Примеры

Измерение продолжительности асинхронных операций

В следующем примере используются Async Hooks и Performance API для измерения фактической продолжительности операции Timeout (включая время выполнения обратного вызова).

'use strict';
const async_hooks = require('async_hooks');
const {
  performance,
  PerformanceObserver
} = require('perf_hooks');

const set = new Set();
const hook = async_hooks.createHook({
  init(id, type) {
    if (type === 'Timeout') {
      performance.mark(`Timeout-${id}-Init`);
      set.add(id);
    }
  },
  destroy(id) {
    if (set.has(id)) {
      set.delete(id);
      performance.mark(`Timeout-${id}-Destroy`);
      performance.measure(`Timeout-${id}`,
                          `Timeout-${id}-Init`,
                          `Timeout-${id}-Destroy`);
    }
  }
});
hook.enable();

const obs = new PerformanceObserver((list, observer) => {
  console.log(list.getEntries()[0]);
  performance.clearMarks();
  observer.disconnect();
});
obs.observe({ entryTypes: ['measure'], buffered: true });

setTimeout(() => {}, 1000);

Измерение времени загрузки зависимостей

В следующем примере измеряется продолжительность require() операций загрузки зависимостей:

'use strict';
const {
  performance,
  PerformanceObserver
} = require('perf_hooks');
const mod = require('module');

// Monkey patch the require function
mod.Module.prototype.require =
  performance.timerify(mod.Module.prototype.require);
require = performance.timerify(require);

// Activate the observer
const obs = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    console.log(`require('${entry[0]}')`, entry.duration);
  });
  obs.disconnect();
});
obs.observe({ entryTypes: ['function'], buffered: true });

require('some-module');

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v12.x/docs/api/perf_hooks.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API