Spec-Zone.ru › Node.js 20 LTS

V8

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

Модуль node:v8 предоставляет API, специфичные для версии V8, встроенной в двоичный файл Node.js. Доступ к нему можно получить с помощью:

const v8 = require('node:v8'); copy

v8.cachedDataVersionTag()

Добавлено в: v8.0.0
  • Возвращает: <integer>

Возвращает целое число, представляющее тег версии, полученный на основе версии V8, флагов командной строки и обнаруженных возможностей процессора. Это полезно для определения того, совместим ли буфер vm.Script cachedData с этим экземпляром V8.

console.log(v8.cachedDataVersionTag()); // 3947234607
// The value returned by v8.cachedDataVersionTag() is derived from the V8
// version, command-line flags, and detected CPU features. Test that the value
// does indeed update when flags are toggled.
v8.setFlagsFromString('--allow_natives_syntax');
console.log(v8.cachedDataVersionTag()); // 183726201 copy

v8.getHeapCodeStatistics()

Добавлено в: v12.8.0
  • Возвращает: <Object>

Получает статистику о коде и его метаданных в куче, см. API V8 GetHeapCodeAndMetadataStatistics. Возвращает объект со следующими свойствами:

  • code_and_metadata_size <number>
  • bytecode_and_metadata_size <number>
  • external_script_source_size <number>
  • cpu_profiler_metadata_size <number>
{
  code_and_metadata_size: 212208,
  bytecode_and_metadata_size: 161368,
  external_script_source_size: 1410794,
  cpu_profiler_metadata_size: 0,
} copy

v8.getHeapSnapshot([options])

История
Версия Изменения
v19.1.0

Добавлена поддержка параметров настройки снимка кучи.

v11.13.0

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

  • options <Object>

    • exposeInternals <boolean> Если значение равно true, внутренние данные будут показаны в снимке кучи. По умолчанию: false.
    • exposeNumericValues <boolean> Если значение равно true, числовые значения будут показаны в искусственных полях. По умолчанию: false.
  • Возвращает: <stream.Readable> Поток Readable, содержащий снимок кучи V8.

Создает снимок текущей кучи V8 и возвращает поток Readable, который можно использовать для чтения сериализованного представления в формате JSON. Этот формат потока JSON предназначен для использования с такими инструментами, как Chrome DevTools. Схема JSON не документирована и специфична для движка V8. Поэтому схема может меняться от одной версии V8 к другой.

Для создания снимка кучи требуется объем памяти примерно вдвое больше размера кучи на момент создания снимка. Это создает риск завершения процесса механизмами OOM killer.

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

// Print heap snapshot to the console
const v8 = require('node:v8');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout); copy

v8.getHeapSpaceStatistics()

История
Версия Изменения
v7.5.0

Добавлена поддержка значений, превышающих диапазон 32-разрядных беззнаковых целых чисел.

v6.0.0

Добавлено в: v6.0.0

  • Возвращает: <Object[]>

Возвращает статистику по пространствам кучи V8, то есть сегментам, из которых состоит куча V8. Ни порядок пространств кучи, ни наличие какого-либо пространства не гарантируются, поскольку статистика предоставляется функцией V8 GetHeapSpaceStatistics и может меняться от одной версии V8 к другой.

Возвращаемое значение — это массив объектов, содержащих следующие свойства:

  • space_name <string>
  • space_size <number>
  • space_used_size <number>
  • space_available_size <number>
  • physical_space_size <number>
[
  {
    "space_name": "new_space",
    "space_size": 2063872,
    "space_used_size": 951112,
    "space_available_size": 80824,
    "physical_space_size": 2063872
  },
  {
    "space_name": "old_space",
    "space_size": 3090560,
    "space_used_size": 2493792,
    "space_available_size": 0,
    "physical_space_size": 3090560
  },
  {
    "space_name": "code_space",
    "space_size": 1260160,
    "space_used_size": 644256,
    "space_available_size": 960,
    "physical_space_size": 1260160
  },
  {
    "space_name": "map_space",
    "space_size": 1094160,
    "space_used_size": 201608,
    "space_available_size": 0,
    "physical_space_size": 1094160
  },
  {
    "space_name": "large_object_space",
    "space_size": 0,
    "space_used_size": 0,
    "space_available_size": 1490980608,
    "physical_space_size": 0
  }
] copy

v8.getHeapStatistics()

История
Версия Изменения
v7.5.0

Добавлена поддержка значений, превышающих диапазон 32-разрядных беззнаковых целых чисел.

v7.2.0

Добавлены malloced_memory, peak_malloced_memory и does_zap_garbage.

v1.0.0

Добавлено в: v1.0.0

  • Возвращает: <Object>

Возвращает объект со следующими свойствами:

  • total_heap_size <number>
  • total_heap_size_executable <number>
  • total_physical_size <number>
  • total_available_size <number>
  • used_heap_size <number>
  • heap_size_limit <number>
  • malloced_memory <number>
  • peak_malloced_memory <number>
  • does_zap_garbage <number>
  • number_of_native_contexts <number>
  • number_of_detached_contexts <number>
  • total_global_handles_size <number>
  • used_global_handles_size <number>
  • external_memory <number>

total_heap_size Значение total_heap_size — это количество байтов, выделенных V8 для кучи. Оно может увеличиваться, если для used_heap требуется больше памяти.

total_heap_size_executable Значение total_heap_size_executable — это часть кучи, в которой может находиться исполняемый код, в байтах. Сюда входит память, используемая кодом, скомпилированным JIT-компилятором, а также память, которая должна оставаться исполняемой.

total_physical_size Значение total_physical_size — это фактически используемая физическая память кучи V8, в байтах. Это объем выделенной (или используемой), а не зарезервированной памяти.

total_available_size Значение total_available_size — это количество байтов памяти, доступных куче V8. Оно показывает, сколько дополнительной памяти может использовать V8 до достижения ограничения размера кучи.

used_heap_size Значение used_heap_size — это количество байтов, используемых в данный момент объектами JavaScript V8. Это фактически используемая память; она не включает память, которая была выделена, но еще не использовалась.

heap_size_limit Значение heap_size_limit — это максимальный размер кучи V8 в байтах (ограничение по умолчанию, определяемое системными ресурсами, или значение, переданное параметру --max_old_space_size).

malloced_memory Значение malloced_memory — это количество байтов, выделенных V8 с помощью malloc.

peak_malloced_memory Значение peak_malloced_memory — это максимальное количество байтов, выделенных V8 с помощью malloc за время существования процесса.

does_zap_garbage — это логическое значение 0/1, указывающее, включен ли параметр --zap_code_space. В этом режиме V8 перезаписывает мусор в куче битовым шаблоном. Объем RSS (размер резидентного набора) увеличивается, поскольку V8 постоянно обращается ко всем страницам кучи, из-за чего операционной системе становится сложнее выгружать их в файл подкачки.

number_of_native_contexts Значение native_context — это количество активных в данный момент контекстов верхнего уровня. Увеличение этого числа со временем указывает на утечку памяти.

number_of_detached_contexts Значение detached_context — это количество контекстов, которые были отсоединены, но еще не собраны сборщиком мусора. Ненулевое значение может указывать на утечку памяти.

total_global_handles_size Значение total_global_handles_size — это общий размер памяти глобальных дескрипторов V8.

used_global_handles_size Значение used_global_handles_size — это размер используемой памяти глобальных дескрипторов V8.

external_memory Значение external_memory — это размер памяти буферов массивов и внешних строк.

{
  total_heap_size: 7326976,
  total_heap_size_executable: 4194304,
  total_physical_size: 7326976,
  total_available_size: 1152656,
  used_heap_size: 3476208,
  heap_size_limit: 1535115264,
  malloced_memory: 16384,
  peak_malloced_memory: 1127496,
  does_zap_garbage: 0,
  number_of_native_contexts: 1,
  number_of_detached_contexts: 0,
  total_global_handles_size: 8192,
  used_global_handles_size: 3296,
  external_memory: 318824
} copy

v8.queryObjects(ctor[, options])

Добавлено в: v20.13.0
Стабильность: 1.1 — Активная разработка
  • ctor <Function> Конструктор, который можно использовать для поиска в цепочке прототипов, чтобы отфильтровать целевые объекты в куче.
  • options <undefined> | <Object>
    • format <string> Если значение равно 'count', возвращается количество совпавших объектов. Если значение равно 'summary', возвращается массив строк со сводной информацией о совпавших объектах.
  • Возвращает: {number|Array}

Этот метод похож на queryObjects() API консоли, предоставляемый консолью Chromium DevTools. Его можно использовать для поиска в куче объектов, в цепочке прототипов которых после полной сборки мусора имеется соответствующий конструктор. Это может быть полезно для регрессионного тестирования утечек памяти. Во избежание неожиданных результатов не следует использовать этот API с конструкторами, реализацию которых вы не контролируете, или с конструкторами, которые могут вызываться другими участниками приложения.

Чтобы избежать случайных утечек, этот API не возвращает прямые ссылки на найденные объекты. По умолчанию он возвращает количество найденных объектов. Если options.format равно 'summary', возвращается массив с краткими строковыми представлениями каждого объекта. Представление данных, предоставляемое этим API, аналогично тому, которое дает снимок кучи, при этом можно избежать затрат на сериализацию и разбор, а также напрямую фильтровать целевые объекты во время поиска.

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

CommonJS
const { queryObjects } = require('node:v8');
class A { foo = 'bar'; }
console.log(queryObjects(A)); // 0
const a = new A();
console.log(queryObjects(A)); // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));

class B extends A { bar = 'qux'; }
const b = new B();
console.log(queryObjects(B)); // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }));

// Note that, when there are child classes inheriting from a constructor,
// the constructor also shows up in the prototype chain of the child
// classes's prototoype, so the child classes's prototoype would also be
// included in the result.
console.log(queryObjects(A));  // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));
Модули JavaScript
import { queryObjects } from 'node:v8';
class A { foo = 'bar'; }
console.log(queryObjects(A)); // 0
const a = new A();
console.log(queryObjects(A)); // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));

class B extends A { bar = 'qux'; }
const b = new B();
console.log(queryObjects(B)); // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }));

// Note that, when there are child classes inheriting from a constructor,
// the constructor also shows up in the prototype chain of the child
// classes's prototoype, so the child classes's prototoype would also be
// included in the result.
console.log(queryObjects(A));  // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));

v8.setFlagsFromString(flags)

Добавлено в: v1.0.0
  • flags <string>

Метод v8.setFlagsFromString() можно использовать для программной установки флагов командной строки V8. Этот метод следует использовать с осторожностью. Изменение настроек после запуска виртуальной машины может привести к непредсказуемому поведению, включая сбои и потерю данных, либо не дать никакого эффекта.

Доступные параметры V8 для версии Node.js можно определить, выполнив node --v8-options.

Использование:

// Print GC events to stdout for one minute.
const v8 = require('node:v8');
v8.setFlagsFromString('--trace_gc');
setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3); copy

v8.stopCoverage()

Добавлено в: v15.1.0, v14.18.0, v12.22.0

Метод v8.stopCoverage() позволяет остановить сбор данных о покрытии, начатый с помощью NODE_V8_COVERAGE, чтобы V8 мог освободить записи счетчиков выполнения и оптимизировать код. Это можно использовать вместе с v8.takeCoverage(), если требуется собирать данные о покрытии по запросу.

v8.takeCoverage()

Добавлено в: v15.1.0, v14.18.0, v12.22.0

Метод v8.takeCoverage() позволяет по запросу записать на диск данные о покрытии, сбор которых был начат с помощью NODE_V8_COVERAGE. Этот метод можно вызывать несколько раз в течение времени существования процесса. При каждом вызове счетчик выполнения будет сбрасываться, а новый отчет о покрытии записываться в каталог, указанный параметром NODE_V8_COVERAGE.

Перед завершением процесса на диск будет записан последний отчет о покрытии, если только до завершения процесса не будет вызван метод v8.stopCoverage().

v8.writeHeapSnapshot([filename[,options]])

История
Версия Изменения
v19.1.0

Добавлена поддержка параметров настройки снимка кучи.

v18.0.0

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

v18.0.0

Коды ошибок приведены к единообразию на всех платформах.

v11.13.0

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

  • filename <string> Путь к файлу, в который нужно сохранить снимок кучи V8. Если не указан, будет создано имя файла по шаблону 'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot', где {pid} — PID процесса Node.js, а {thread_id} будет равно 0 при вызове writeHeapSnapshot() из основного потока Node.js или идентификатору рабочего потока.
  • options <Object>
    • exposeInternals <boolean> Если значение равно true, внутренние данные будут показаны в снимке кучи. По умолчанию: false.
    • exposeNumericValues <boolean> Если значение равно true, числовые значения будут показаны в искусственных полях. По умолчанию: false.
  • Возвращает: <string> Имя файла, в который был сохранен снимок.

Создает снимок текущей кучи V8 и записывает его в файл JSON. Этот файл предназначен для использования с такими инструментами, как Chrome DevTools. Схема JSON не документирована и специфична для движка V8 и может меняться от одной версии V8 к другой.

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

Для создания снимка кучи требуется объем памяти примерно вдвое больше размера кучи на момент создания снимка. Это создает риск завершения процесса механизмами OOM killer.

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

const { writeHeapSnapshot } = require('node:v8');
const {
  Worker,
  isMainThread,
  parentPort,
} = require('node:worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename);

  worker.once('message', (filename) => {
    console.log(`worker heapdump: ${filename}`);
    // Now get a heapdump for the main thread.
    console.log(`main thread heapdump: ${writeHeapSnapshot()}`);
  });

  // Tell the worker to create a heapdump.
  worker.postMessage('heapdump');
} else {
  parentPort.once('message', (message) => {
    if (message === 'heapdump') {
      // Generate a heapdump for the worker
      // and return the filename to the parent.
      parentPort.postMessage(writeHeapSnapshot());
    }
  });
} copy

v8.setHeapSnapshotNearHeapLimit(limit)

Добавлено в: v18.10.0, v16.18.0
Стабильность: 1 — Экспериментальный
  • limit <integer>

API ничего не делает, если --heapsnapshot-near-heap-limit уже задан в командной строке или если API вызывается более одного раза. limit должно быть положительным целым числом. Дополнительные сведения см. в разделе --heapsnapshot-near-heap-limit.

API сериализации

API сериализации предоставляет средства для сериализации значений JavaScript способом, совместимым с алгоритмом структурированного клонирования HTML.

Формат обратно совместим (то есть его безопасно сохранять на диск). Одинаковые значения JavaScript могут приводить к разным сериализованным результатам.

v8.serialize(value)

Добавлено в: v8.0.0
  • value <any>
  • Возвращает: <Buffer>

Использует DefaultSerializer для сериализации value в буфер.

При попытке сериализовать огромный объект, для которого требуется буфер размером больше buffer.constants.MAX_LENGTH, будет выброшено исключение ERR_BUFFER_TOO_LARGE.

v8.deserialize(buffer)

Добавлено в: v8.0.0
  • buffer <Buffer> | <TypedArray> | <DataView> Буфер, возвращённый serialize().

Использует DefaultDeserializer с параметрами по умолчанию для чтения значения JS из буфера.

Класс: v8.Serializer

Добавлено в: v8.0.0
new Serializer()

Создаёт новый объект Serializer.

serializer.writeHeader()

Записывает заголовок, содержащий версию формата сериализации.

serializer.writeValue(value)
  • value <any>

Сериализует значение JavaScript и добавляет его сериализованное представление во внутренний буфер.

Если value невозможно сериализовать, будет выброшена ошибка.

serializer.releaseBuffer()
  • Возвращает: <Buffer>

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

serializer.transferArrayBuffer(id, arrayBuffer)
  • id <integer> 32-разрядное беззнаковое целое число.
  • arrayBuffer <ArrayBuffer> Экземпляр ArrayBuffer.

Помечает ArrayBuffer как объект, содержимое которого передаётся вне основного потока. Передайте соответствующий ArrayBuffer в контексте десериализации методу deserializer.transferArrayBuffer().

serializer.writeUint32(value)
  • value <integer>

Записывает необработанное 32-разрядное беззнаковое целое число. Предназначено для использования в пользовательском serializer._writeHostObject().

serializer.writeUint64(hi, lo)
  • hi <integer>
  • lo <integer>

Записывает необработанное 64-разрядное беззнаковое целое число, разделённое на старшую и младшую 32-разрядные части. Предназначено для использования в пользовательском serializer._writeHostObject().

serializer.writeDouble(value)
  • value <number>

Записывает значение number JS. Предназначено для использования в пользовательском serializer._writeHostObject().

serializer.writeRawBytes(buffer)
  • buffer <Buffer> | <TypedArray> | <DataView>

Записывает необработанные байты во внутренний буфер сериализатора. Десериализатору потребуется способ вычисления длины буфера. Предназначено для использования в пользовательском serializer._writeHostObject().

serializer._writeHostObject(object)
  • object <Object>

Этот метод вызывается для записи объекта-хоста, то есть объекта, созданного нативными привязками C++. Если сериализовать object невозможно, следует выбросить соответствующее исключение.

Этот метод отсутствует в самом классе Serializer, но его можно реализовать в подклассах.

serializer._getDataCloneError(message)
  • message <string>

Этот метод вызывается для создания объектов ошибок, которые будут выброшены, если объект невозможно клонировать.

По умолчанию этот метод использует конструктор Error; его можно переопределить в подклассах.

serializer._getSharedArrayBufferId(sharedArrayBuffer)
  • sharedArrayBuffer <SharedArrayBuffer>

Этот метод вызывается, когда сериализатор собирается сериализовать объект SharedArrayBuffer. Он должен возвращать беззнаковый 32-разрядный идентификатор объекта, используя тот же идентификатор, если этот SharedArrayBuffer уже сериализован. При десериализации этот идентификатор будет передан методу deserializer.transferArrayBuffer().

Если объект невозможно сериализовать, следует выбросить исключение.

Этот метод отсутствует в самом классе Serializer, но его можно реализовать в подклассах.

serializer._setTreatArrayBufferViewsAsHostObjects(flag)
  • flag <boolean> По умолчанию: false

Указывает, следует ли обрабатывать объекты TypedArray и DataView как объекты-хосты, то есть передавать их методу serializer._writeHostObject().

Класс: v8.Deserializer

Добавлено в: v8.0.0
new Deserializer(buffer)
  • buffer <Buffer> | <TypedArray> | <DataView> Буфер, возвращённый методом serializer.releaseBuffer().

Создаёт новый объект Deserializer.

deserializer.readHeader()

Читает и проверяет заголовок (включая версию формата). Например, метод может отклонить недопустимый или неподдерживаемый формат передачи данных. В этом случае выбрасывается Error.

deserializer.readValue()

Десериализует значение JavaScript из буфера и возвращает его.

deserializer.transferArrayBuffer(id, arrayBuffer)
  • id <integer> 32-разрядное беззнаковое целое число.
  • arrayBuffer <ArrayBuffer> | <SharedArrayBuffer> Экземпляр ArrayBuffer.

Помечает ArrayBuffer как объект, содержимое которого передаётся вне основного потока. Передайте соответствующий ArrayBuffer в контексте сериализации методу serializer.transferArrayBuffer() (или верните id из serializer._getSharedArrayBufferId() для объектов SharedArrayBuffer).

deserializer.getWireFormatVersion()
  • Возвращает: <integer>

Читает версию используемого формата передачи данных. Вероятно, этот метод пригодится главным образом устаревшему коду, который читает старые версии формата. Его нельзя вызывать до .readHeader().

deserializer.readUint32()
  • Возвращает: <integer>

Читает и возвращает необработанное 32-разрядное беззнаковое целое число. Предназначено для использования в пользовательском deserializer._readHostObject().

deserializer.readUint64()
  • Возвращает: <integer[]>

Читает необработанное 64-разрядное беззнаковое целое число и возвращает его в виде массива [hi, lo] с двумя 32-разрядными беззнаковыми целыми числами. Предназначено для использования в пользовательском deserializer._readHostObject().

deserializer.readDouble()
  • Возвращает: <number>

Читает значение number JS. Предназначено для использования в пользовательском deserializer._readHostObject().

deserializer.readRawBytes(length)
  • length <integer>
  • Возвращает: <Buffer>

Читает необработанные байты из внутреннего буфера десериализатора. Параметр length должен соответствовать длине буфера, переданного методу serializer.writeRawBytes(). Предназначено для использования в пользовательском deserializer._readHostObject().

deserializer._readHostObject()

Этот метод вызывается для чтения объекта-хоста, то есть объекта, созданного нативными привязками C++. Если десериализовать данные невозможно, следует выбросить соответствующее исключение.

Этот метод отсутствует в самом классе Deserializer, но его можно реализовать в подклассах.

Класс: v8.DefaultSerializer

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

Подкласс Serializer, который сериализует TypedArray (в частности, Buffer) и объекты DataView как объекты-хосты и сохраняет только ту часть их базовых ArrayBuffer, на которую они ссылаются.

Класс: v8.DefaultDeserializer

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

Подкласс Deserializer, соответствующий формату, записываемому классом DefaultSerializer.

Хуки Promise

Интерфейс promiseHooks можно использовать для отслеживания событий жизненного цикла промисов. Чтобы отслеживать всю асинхронную активность, см. async_hooks, который внутри использует этот модуль для создания событий жизненного цикла промисов, а также событий для других асинхронных ресурсов. Для управления контекстом запросов см. AsyncLocalStorage.

import { promiseHooks } from 'node:v8';

// There are four lifecycle events produced by promises:

// The `init` event represents the creation of a promise. This could be a
// direct creation such as with `new Promise(...)` or a continuation such
// as `then()` or `catch()`. It also happens whenever an async function is
// called or does an `await`. If a continuation promise is created, the
// `parent` will be the promise it is a continuation from.
function init(promise, parent) {
  console.log('a promise was created', { promise, parent });
}

// The `settled` event happens when a promise receives a resolution or
// rejection value. This may happen synchronously such as when using
// `Promise.resolve()` on non-promise input.
function settled(promise) {
  console.log('a promise resolved or rejected', { promise });
}

// The `before` event runs immediately before a `then()` or `catch()` handler
// runs or an `await` resumes execution.
function before(promise) {
  console.log('a promise is about to call a then handler', { promise });
}

// The `after` event runs immediately after a `then()` handler runs or when
// an `await` begins after resuming from another.
function after(promise) {
  console.log('a promise is done calling a then handler', { promise });
}

// Lifecycle hooks may be started and stopped individually
const stopWatchingInits = promiseHooks.onInit(init);
const stopWatchingSettleds = promiseHooks.onSettled(settled);
const stopWatchingBefores = promiseHooks.onBefore(before);
const stopWatchingAfters = promiseHooks.onAfter(after);

// Or they may be started and stopped in groups
const stopHookSet = promiseHooks.createHook({
  init,
  settled,
  before,
  after,
});

// To stop a hook, call the function returned at its creation.
stopWatchingInits();
stopWatchingSettleds();
stopWatchingBefores();
stopWatchingAfters();
stopHookSet(); copy

promiseHooks.onInit(init)

Добавлено в: v17.1.0, v16.14.0
  • init <Function> Функция обратного вызова init, вызываемая при создании промиса.
  • Возвращает: <Function> Вызовите, чтобы остановить хук.

Хук init должен быть обычной функцией. Передача асинхронной функции приведёт к ошибке, поскольку она создаст бесконечный цикл микрозадач.

Модули JavaScript
import { promiseHooks } from 'node:v8';

const stop = promiseHooks.onInit((promise, parent) => {});
CommonJS
const { promiseHooks } = require('node:v8');

const stop = promiseHooks.onInit((promise, parent) => {});

promiseHooks.onSettled(settled)

Добавлено в: v17.1.0, v16.14.0
  • settled <Function> Функция обратного вызова settled, вызываемая при выполнении промиса или его отклонении.
  • Возвращает: <Function> Вызовите, чтобы остановить хук.

Хук settled должен быть обычной функцией. Передача асинхронной функции приведёт к ошибке, поскольку она создаст бесконечный цикл микрозадач.

Модули JavaScript
import { promiseHooks } from 'node:v8';

const stop = promiseHooks.onSettled((promise) => {});
CommonJS
const { promiseHooks } = require('node:v8');

const stop = promiseHooks.onSettled((promise) => {});

promiseHooks.onBefore(before)

Добавлено в: v17.1.0, v16.14.0
  • before <Function> Функция обратного вызова before, вызываемая перед выполнением продолжения промиса.
  • Возвращает: <Function> Вызовите, чтобы остановить хук.

Хук before должен быть обычной функцией. Передача асинхронной функции приведёт к ошибке, поскольку она создаст бесконечный цикл микрозадач.

Модули JavaScript
import { promiseHooks } from 'node:v8';

const stop = promiseHooks.onBefore((promise) => {});
CommonJS
const { promiseHooks } = require('node:v8');

const stop = promiseHooks.onBefore((promise) => {});

promiseHooks.onAfter(after)

Добавлено в: v17.1.0, v16.14.0
  • after <Function> Функция обратного вызова after, вызываемая после выполнения продолжения промиса.
  • Возвращает: <Function> Вызовите, чтобы остановить хук.

Хук after должен быть обычной функцией. Передача асинхронной функции приведёт к ошибке, поскольку она создаст бесконечный цикл микрозадач.

Модули JavaScript
import { promiseHooks } from 'node:v8';

const stop = promiseHooks.onAfter((promise) => {});
CommonJS
const { promiseHooks } = require('node:v8');

const stop = promiseHooks.onAfter((promise) => {});

promiseHooks.createHook(callbacks)

Добавлено в: v17.1.0, v16.14.0
  • callbacks <Object> Функции обратного вызова хуков для регистрации (функции обратного вызова хуков)
    • init <Function> Функция обратного вызова init.
    • before <Function> Функция обратного вызова before.
    • after <Function> Функция обратного вызова after.
    • settled <Function> Функция обратного вызова settled.
  • Возвращает: <Function> Используется для отключения хуков

Функции обратного вызова хуков должны быть обычными функциями. Передача асинхронных функций приведёт к ошибке, поскольку они создадут бесконечный цикл микрозадач.

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

Функции обратного вызова init()/before()/after()/settled() вызываются при соответствующих событиях жизненного цикла промиса.

Все функции обратного вызова необязательны. Например, если нужно отслеживать только создание промиса, достаточно передать функцию обратного вызова init. Описание всех функций, которые можно передать в callbacks, приведено в разделе Функции обратного вызова хуков.

Модули JavaScript
import { promiseHooks } from 'node:v8';

const stopAll = promiseHooks.createHook({
  init(promise, parent) {},
});
CommonJS
const { promiseHooks } = require('node:v8');

const stopAll = promiseHooks.createHook({
  init(promise, parent) {},
});

Функции обратного вызова хуков

Ключевые события жизненного цикла промиса разделены на четыре категории: создание промиса, момент до и после вызова обработчика продолжения или выполнение await, а также разрешение или отклонение промиса.

Хотя эти хуки похожи на хуки async_hooks, в них отсутствует хук destroy. Другие типы асинхронных ресурсов обычно представляют собой сокеты или файловые дескрипторы, у которых есть отдельное состояние «закрыт», обозначающее событие жизненного цикла destroy; промисы же остаются пригодными для использования, пока код может к ним обратиться. Чтобы вписать промисы в модель событий async_hooks, используется отслеживание сборки мусора, однако оно требует значительных ресурсов, и сборка мусора для промисов может так и не произойти.

Поскольку промисы являются асинхронными ресурсами, жизненный цикл которых отслеживается механизмом хуков промисов, функции обратного вызова init(), before(), after() и settled() не должны быть асинхронными функциями, поскольку они создают дополнительные промисы, что привело бы к бесконечному циклу.

Хотя этот API используется для передачи событий промисов в async_hooks, порядок вызовов двух API не определён. Оба API поддерживают нескольких пользователей, поэтому события каждого из них могут возникать в любом порядке относительно событий другого.

init(promise, parent)
  • promise <Promise> Создаваемый промис.
  • parent <Promise> Промис, от которого продолжается выполнение, если применимо.

Вызывается при создании промиса. Это не означает, что обязательно произойдут соответствующие события before/after; это означает лишь, что такая возможность существует. Это происходит, если промис создан, но для него так и не было задано продолжение.

before(promise)
  • promise <Promise>

Вызывается перед выполнением продолжения промиса. Это может быть обработчик then(), catch() или finally() либо возобновление await.

Функция обратного вызова before будет вызвана от 0 до N раз. Функция обратного вызова before обычно не вызывается, если для промиса ни разу не было задано продолжение. Функция обратного вызова before может вызываться много раз, если для одного и того же промиса было задано много продолжений.

after(promise)
  • promise <Promise>

Вызывается сразу после выполнения продолжения промиса. Это может произойти после обработчика then(), catch() или finally() либо перед await после другого await.

settled(promise)
  • promise <Promise>

Вызывается, когда промис получает значение успешного выполнения или отклонения. Это может произойти синхронно в случае Promise.resolve() или Promise.reject().

API снимков состояния при запуске

Добавлено в: v18.6.0, v16.17.0
Стабильность: 1 — Экспериментальный

Интерфейс v8.startupSnapshot можно использовать для добавления хуков сериализации и десериализации пользовательских снимков состояния при запуске.

$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# This launches a process with the snapshot
$ node --snapshot-blob snapshot.blob copy

В приведённом выше примере entry.js может использовать методы интерфейса v8.startupSnapshot, чтобы указать, как сохранять сведения о пользовательских объектах в снимке во время сериализации и как использовать эти сведения для синхронизации объектов при десериализации снимка. Например, если entry.js содержит следующий скрипт:

'use strict';

const fs = require('node:fs');
const zlib = require('node:zlib');
const path = require('node:path');
const assert = require('node:assert');

const v8 = require('node:v8');

class BookShelf {
  storage = new Map();

  // Reading a series of files from directory and store them into storage.
  constructor(directory, books) {
    for (const book of books) {
      this.storage.set(book, fs.readFileSync(path.join(directory, book)));
    }
  }

  static compressAll(shelf) {
    for (const [ book, content ] of shelf.storage) {
      shelf.storage.set(book, zlib.gzipSync(content));
    }
  }

  static decompressAll(shelf) {
    for (const [ book, content ] of shelf.storage) {
      shelf.storage.set(book, zlib.gunzipSync(content));
    }
  }
}

// __dirname here is where the snapshot script is placed
// during snapshot building time.
const shelf = new BookShelf(__dirname, [
  'book1.en_US.txt',
  'book1.es_ES.txt',
  'book2.zh_CN.txt',
]);

assert(v8.startupSnapshot.isBuildingSnapshot());
// On snapshot serialization, compress the books to reduce size.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf);
// On snapshot deserialization, decompress the books.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf);
v8.startupSnapshot.setDeserializeMainFunction((shelf) => {
  // process.env and process.argv are refreshed during snapshot
  // deserialization.
  const lang = process.env.BOOK_LANG || 'en_US';
  const book = process.argv[1];
  const name = `${book}.${lang}.txt`;
  console.log(shelf.storage.get(name));
}, shelf); copy

При запуске полученный двоичный файл выведет данные, десериализованные из снимка, используя обновлённые process.env и process.argv запущенного процесса:

$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Prints content of book1.es_ES.txt deserialized from the snapshot. copy

В настоящее время приложение, десериализованное из пользовательского снимка, нельзя снова сохранить в виде снимка, поэтому эти API доступны только приложениям, которые не были десериализованы из пользовательского снимка.

v8.startupSnapshot.addSerializeCallback(callback[, data])

Добавлено в: v18.6.0, v16.17.0
  • callback <Function> Функция обратного вызова, вызываемая перед сериализацией.
  • data <any> Необязательные данные, которые будут переданы функции callback при её вызове.

Добавляет функцию обратного вызова, которая будет вызвана перед сериализацией экземпляра Node.js в снимок и его завершением. Её можно использовать для освобождения ресурсов, которые не следует или невозможно сериализовать, либо для преобразования пользовательских данных в более подходящий для сериализации формат.

Функции обратного вызова выполняются в порядке добавления.

v8.startupSnapshot.addDeserializeCallback(callback[, data])

Добавлено в: v18.6.0, v16.17.0
  • callback <Function> Функция обратного вызова, вызываемая после десериализации снимка.
  • data <any> Необязательные данные, которые будут переданы функции callback при её вызове.

Добавляет функцию обратного вызова, которая будет вызвана при десериализации экземпляра Node.js из снимка. callback и data (если указаны) будут сериализованы в снимок; их можно использовать для повторной инициализации состояния приложения или повторного получения ресурсов, необходимых приложению после его перезапуска из снимка.

Функции обратного вызова выполняются в порядке добавления.

v8.startupSnapshot.setDeserializeMainFunction(callback[, data])

Добавлено в: v18.6.0, v16.17.0
  • callback <Function> Функция обратного вызова, вызываемая в качестве точки входа после десериализации снимка.
  • data <any> Необязательные данные, которые будут переданы функции callback при её вызове.

Задаёт точку входа приложения Node.js при его десериализации из снимка. Этот метод можно вызвать только один раз в скрипте создания снимка. Если он вызван, для запуска десериализованного приложения больше не требуется дополнительный скрипт точки входа: будет вызвана функция обратного вызова вместе с десериализованными данными (если они предоставлены). В противном случае для десериализованного приложения по-прежнему потребуется скрипт точки входа.

v8.startupSnapshot.isBuildingSnapshot()

Добавлено в: v18.6.0, v16.17.0
  • Возвращает: <boolean>

Возвращает true, если экземпляр Node.js запущен для создания снимка.

Класс: v8.GCProfiler

Добавлено в: v19.6.0, v18.15.0

Этот API собирает данные GC в текущем потоке.

new v8.GCProfiler()

Добавлено в: v19.6.0, v18.15.0

Создаёт новый экземпляр класса v8.GCProfiler.

profiler.start()

Добавлено в: v19.6.0, v18.15.0

Начинает сбор данных GC.

profiler.stop()

Добавлено в: v19.6.0, v18.15.0

Останавливает сбор данных GC и возвращает объект. Содержимое объекта выглядит следующим образом.

{
  "version": 1,
  "startTime": 1674059033862,
  "statistics": [
    {
      "gcType": "Scavenge",
      "beforeGC": {
        "heapStatistics": {
          "totalHeapSize": 5005312,
          "totalHeapSizeExecutable": 524288,
          "totalPhysicalSize": 5226496,
          "totalAvailableSize": 4341325216,
          "totalGlobalHandlesSize": 8192,
          "usedGlobalHandlesSize": 2112,
          "usedHeapSize": 4883840,
          "heapSizeLimit": 4345298944,
          "mallocedMemory": 254128,
          "externalMemory": 225138,
          "peakMallocedMemory": 181760
        },
        "heapSpaceStatistics": [
          {
            "spaceName": "read_only_space",
            "spaceSize": 0,
            "spaceUsedSize": 0,
            "spaceAvailableSize": 0,
            "physicalSpaceSize": 0
          }
        ]
      },
      "cost": 1574.14,
      "afterGC": {
        "heapStatistics": {
          "totalHeapSize": 6053888,
          "totalHeapSizeExecutable": 524288,
          "totalPhysicalSize": 5500928,
          "totalAvailableSize": 4341101384,
          "totalGlobalHandlesSize": 8192,
          "usedGlobalHandlesSize": 2112,
          "usedHeapSize": 4059096,
          "heapSizeLimit": 4345298944,
          "mallocedMemory": 254128,
          "externalMemory": 225138,
          "peakMallocedMemory": 181760
        },
        "heapSpaceStatistics": [
          {
            "spaceName": "read_only_space",
            "spaceSize": 0,
            "spaceUsedSize": 0,
            "spaceAvailableSize": 0,
            "physicalSpaceSize": 0
          }
        ]
      }
    }
  ],
  "endTime": 1674059036865
} copy

Пример.

const { GCProfiler } = require('v8');
const profiler = new GCProfiler();
profiler.start();
setTimeout(() => {
  console.log(profiler.stop());
}, 1000); copy

© 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-v20.x/docs/api/v8.html

Spec-Zone.ru

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