V8
Исходный код: lib/v8.js
Модуль node:v8 предоставляет API, специфичные для версии V8, встроенной в бинарник Node.js. К нему можно получить доступ с помощью:
const v8 = require('node:v8'); copy
v8.cachedDataVersionTag()
- Возвращает: <целое число>
Возвращает целое число, представляющее метку версии, полученную из версии 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()
- Возвращает: <Объект>
Получение статистики о коде и его метаданных в куче, см. V8 GetHeapCodeAndMetadataStatistics API. Возвращает объект со следующими свойствами:
-
code_and_metadata_size<число> -
bytecode_and_metadata_size<число> -
external_script_source_size<число> -
cpu_profiler_metadata_size<число>
{
code_and_metadata_size: 212208,
bytecode_and_metadata_size: 161368,
external_script_source_size: 1410794,
cpu_profiler_metadata_size: 0,
} copy
v8.getHeapSnapshot()
- Возвращает: <Поток.Readable> Поток Readable, содержащий дамп кучи V8
Создаёт дамп текущей кучи V8 и возвращает потоковый объект Readable, который может использоваться для чтения сериализованного представления в формате JSON. Этот формат JSON предназначен для использования с такими инструментами, как Chrome DevTools. Схема JSON не документирована и специфична для движка V8. Поэтому схема может изменяться от одной версии V8 к другой.
Создание снимка кучи требует памяти примерно в два раза больше размера кучи на момент создания снимка. Это приводит к риску завершения процесса из-за OOM-киллера.
Генерация снимка — это синхронная операция, блокирующая цикл событий на время, зависящее от размера кучи.
// Print heap snapshot to the console
const v8 = require('node:v8');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout); copy
v8.getHeapSpaceStatistics()
- Возвращает: <Массив объектов>
Возвращает статистику о пространствах кучи V8, то есть сегментах, составляющих кучу V8. Порядок пространств кучи, а также доступность пространства кучи не гарантируются, так как статистика предоставляется функцией V8 GetHeapSpaceStatistics и может меняться от одной версии V8 к другой.
Возвращаемое значение — массив объектов, содержащих следующие свойства:
-
space_name<строка> -
space_size<число> -
space_used_size<число> -
space_available_size<число> -
physical_space_size<число>
[
{
"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()
- Возвращает: <Объект>
Возвращает объект со следующими свойствами:
-
total_heap_size<число> -
total_heap_size_executable<число> -
total_physical_size<число> -
total_available_size<число> -
used_heap_size<число> -
heap_size_limit<число> -
malloced_memory<число> -
peak_malloced_memory<число> -
does_zap_garbage<число> -
number_of_native_contexts<число> -
number_of_detached_contexts<число> -
total_global_handles_size<число> -
used_global_handles_size<число> -
external_memory<число>
does_zap_garbage — булево значение (0/1), обозначающее, включён ли параметр --zap_code_space. Это позволяет V8 перезаписывать мусор кучи определённым битовым шаблоном. Следовательно, размер набора резидентных страниц (RSS) увеличивается, поскольку он постоянно обращается ко всем страницам кучи, что снижает вероятность их вытеснения операционной системой.
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.setFlagsFromString(flags)
-
flags<строка>
Метод 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()
Метод v8.stopCoverage() позволяет пользователю остановить сборку покрытия, начатую в NODE_V8_COVERAGE, чтобы V8 мог освободить записи счётчиков выполнения и оптимизировать код. Это можно использовать совместно с v8.takeCoverage(), если пользователь хочет собрать покрытие по требованию.
v8.takeCoverage()
Метод v8.takeCoverage() позволяет пользователю записать покрытие, начатое в NODE_V8_COVERAGE, на диск по требованию. Этот метод можно вызывать несколько раз за время работы процесса. При каждом вызове счётчик выполнения будет сброшен, и новый отчёт о покрытии будет записан в каталог, указанный в NODE_V8_COVERAGE.
При завершении процесса последний дамп покрытия всё равно будет записан на диск, если метод v8.stopCoverage() не был вызван перед завершением процесса.
v8.writeHeapSnapshot([filename])
-
filename<строка> Путь к файлу, в который будет сохранён дамп кучи V8. Если не указано, будет сгенерировано имя файла с шаблоном'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot', где{pid}— PID процесса Node.js,{thread_id}—0, когдаwriteHeapSnapshot()вызывается из основного потока Node.js или идентификатор потока-рабочего. - Возвращает: <строка> Имя файла, в который был сохранён дамп.
Создаёт дамп текущей кучи V8 и записывает его в JSON-файл. Этот файл предназначен для использования с инструментами, такими как Chrome DevTools. Схема JSON не документирована и специфична для движка V8, и может меняться от одной версии V8 к другой.
Дамп кучи специфичен для отдельной изоляции V8. При использовании потоков-работников дамп кучи, созданный из основного потока, не будет содержать никакой информации о рабочих потоках, и наоборот.
Создание дампа кучи требует памяти примерно в два раза больше, чем размер кучи в момент создания дампа. Это приводит к риску завершения процесса по причине исчерпания памяти.
Генерация дампа — синхронная операция, которая блокирует цикл событий на время, зависящее от размера кучи.
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)
-
limit<целое число>
API является пустой операцией, если --heapsnapshot-near-heap-limit уже задано из командной строки или API вызывается более одного раза. limit должно быть положительным целым числом. Подробнее см. --heapsnapshot-near-heap-limit.
API сериализации
API сериализации предоставляет средства сериализации значений JavaScript таким образом, чтобы они были совместимы с алгоритмом структурированного клонирования HTML.
Формат обратно совместим (т. е. его безопасно сохранять на диск). Равные значения JavaScript могут привести к различному сериализованному выводу.
v8.serialize(value)
Использует DefaultSerializer для сериализации value в буфер.
ERR_BUFFER_TOO_LARGE будет выброшен при попытке сериализовать большой объект, для которого требуется буфер размером больше, чем buffer.constants.MAX_LENGTH.
v8.deserialize(buffer)
-
buffer<Буфер> | <Массив типов> | <DataView> Буфер, возвращённый функциейserialize().
Использует DefaultDeserializer с параметрами по умолчанию для чтения значения JS из буфера.
Класс: v8.Serializer
new Serializer()
Создаёт новый объект Serializer.
serializer.writeHeader()
Записывает заголовок, который включает версию формата сериализации.
serializer.writeValue(value)
-
value<любое>
Сериализует значение JavaScript и добавляет сериализованное представление во внутренний буфер.
Выбрасывает ошибку, если value не может быть сериализован.
serializer.releaseBuffer()
- Возвращает: <Буфер>
Возвращает сохранённый внутренний буфер. Данный сериализатор больше не должен использоваться после освобождения буфера. Вызов этого метода приводит к неопределённому поведению, если предыдущий запис не удался.
serializer.transferArrayBuffer(id, arrayBuffer)
-
id<целое без знака 32 бита> Целое без знака 32-битное. -
arrayBuffer<ArrayBuffer> ЭкземплярArrayBuffer.
Помечает ArrayBuffer как содержащий данные, которые передаются вне области. Передайте соответствующий ArrayBuffer в контексте десериализации в deserializer.transferArrayBuffer().
serializer.writeUint32(value)
-
value<целое>
Записать целое без знака 32 бита. Для использования внутри пользовательского serializer._writeHostObject().
serializer.writeUint64(hi, lo)
Записать целое без знака 64 бита, разделенное на части по 32 бита (высокая и низкая). Для использования внутри пользовательского serializer._writeHostObject().
serializer.writeDouble(value)
-
value<число>
Записать JS number значение. Для использования внутри пользовательского serializer._writeHostObject().
serializer.writeRawBytes(buffer)
-
buffer<Буфер> | <Массив типов> | <DataView>
Записать сырые байты во внутренний буфер сериализатора. Десериализатор потребует способ вычисления длины буфера. Для использования внутри пользовательского serializer._writeHostObject().
serializer._writeHostObject(object)
-
object<Объект>
Этот метод вызывается для записи некоторого типа объекта хоста, т. е. объекта, созданного с помощью нативных C++ привязок. Если сериализация object невозможна, следует выбросить соответствующую ошибку.
Этот метод не присутствует в классе Serializer сам по себе, но может быть предоставлен подклассами.
serializer._getDataCloneError(message)
-
message<строка>
Этот метод вызывается для генерации объектов ошибок, которые будут выброшены, когда объект не может быть клонирован.
По умолчанию этот метод использует конструктор Error, и его можно переопределить в подклассах.
serializer._getSharedArrayBufferId(sharedArrayBuffer)
-
sharedArrayBuffer<SharedArrayBuffer>
Этот метод вызывается, когда сериализатор собирается сериализовать объект SharedArrayBuffer. Он должен вернуть целое без знака 32-битное ID для объекта, используя то же ID, если этот SharedArrayBuffer уже был сериализован. При десериализации это ID будет передано в deserializer.transferArrayBuffer().
Если объект не может быть сериализован, следует выбросить исключение.
Этот метод не присутствует в классе Serializer сам по себе, но может быть предоставлен подклассами.
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
-
flag<логическое> По умолчанию:false
Указывает, нужно ли рассматривать объекты TypedArray и DataView как объекты хоста, т. е. передавать их в serializer._writeHostObject().
Класс: v8.Deserializer
new Deserializer(buffer)
-
buffer<Буфер> | <Массив типов> | <DataView> Буфер, возвращённыйserializer.releaseBuffer().
Создаёт новый объект Deserializer.
deserializer.readHeader()
Читает и проверяет заголовок (включая версию формата). Может, например, отклонить недействительный или неподдерживаемый формат данных. В этом случае будет выброшено исключение Error.
deserializer.readValue()
Десериализует значение JavaScript из буфера и возвращает его.
deserializer.transferArrayBuffer(id, arrayBuffer)
-
id<целое без знака 32 бита> Целое без знака 32-битное. -
arrayBuffer<ArrayBuffer> | <SharedArrayBuffer> ЭкземплярArrayBuffer.
Помечает ArrayBuffer как содержащий данные, которые передаются вне области. Передайте соответствующий ArrayBuffer в контексте сериализации в serializer.transferArrayBuffer() (или верните id из serializer._getSharedArrayBufferId() в случае SharedArrayBuffer).
deserializer.getWireFormatVersion()
- Возвращает: <целое>
Считывает версию основного формата данных. Вероятно, полезно в основном для устаревшего кода, читающего старые версии формата данных. Возможно не вызывается перед .readHeader().
deserializer.readUint32()
- Возвращает: <целое>
Прочитать целое без знака 32 бита и вернуть его. Для использования внутри пользовательского deserializer._readHostObject().
deserializer.readUint64()
- Возвращает: <массив целых>
Прочитать целое без знака 64 бита и вернуть его как массив [hi, lo] с двумя элементами по 32 бита. Для использования внутри пользовательского deserializer._readHostObject().
deserializer.readDouble()
- Возвращает: <число>
Прочитать JS number значение. Для использования внутри пользовательского deserializer._readHostObject().
deserializer.readRawBytes(length)
Считывает сырые байты из внутреннего буфера десериализатора. Параметр length должен соответствовать длине буфера, который был передан в serializer.writeRawBytes(). Для использования внутри пользовательского deserializer._readHostObject().
deserializer._readHostObject()
Этот метод вызывается для чтения какого-либо объекта хоста, то есть объекта, созданного нативным C++ связующим. Если десериализация данных невозможна, должно быть выброшено соответствующее исключение.
Этот метод отсутствует в самом классе Deserializer, но может быть предоставлен подклассами.
Класс: v8.DefaultSerializer
Подкласс Serializer, который сериализует TypedArray (в частности, Buffer) и DataView объекты как объекты хоста, и хранит только часть их базовых ArrayBuffer на которые они ссылаются.
Класс: v8.DefaultDeserializer
Подкласс Deserializer, соответствующий формату, записанному DefaultSerializer.
Хук-функции для промисов
Интерфейс 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)
-
init<Функция> Обратный вызовinitcallback для вызова при создании промиса. - Возвращает: <Функция> Вызов для остановки хука.
Хук init должен быть обычной функцией. Предоставление асинхронной функции приведет к ошибке, так как это создаст бесконечный цикл микрозадач.
Модули MJS
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onInit((promise, parent) => {});
Модули CJS
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onInit((promise, parent) => {});
promiseHooks.onSettled(settled)
-
settled<Функция> Обратный вызовsettledcallback для вызова, когда промис разрешен или отклонен. - Возвращает: <Функция> Вызов для остановки хука.
Хук settled должен быть обычной функцией. Предоставление асинхронной функции приведет к ошибке, так как это создаст бесконечный цикл микрозадач.
Модули MJS
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onSettled((promise) => {});
Модули CJS
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onSettled((promise) => {});
promiseHooks.onBefore(before)
-
before<Функция> Обратный вызовbeforecallback для вызова перед выполнением продолжения промиса. - Возвращает: <Функция> Вызов для остановки хука.
Хук before должен быть обычной функцией. Предоставление асинхронной функции приведет к ошибке, так как это создаст бесконечный цикл микрозадач.
Модули MJS
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onBefore((promise) => {});
Модули CJS
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onBefore((promise) => {});
promiseHooks.onAfter(after)
-
after<Функция> Обратный вызовaftercallback для вызова после выполнения продолжения промиса. - Возвращает: <Функция> Вызов для остановки хука.
Хук after должен быть обычной функцией. Предоставление асинхронной функции приведет к ошибке, так как это создаст бесконечный цикл микрозадач.
Модули MJS
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onAfter((promise) => {});
Модули CJS
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onAfter((promise) => {});
promiseHooks.createHook(callbacks)
-
callbacks<Объект> Обратные вызовы Hook Callbacks для регистрации-
init<Функция> Обратный вызовinitcallback. -
before<Функция> Обратный вызовbeforecallback. -
after<Функция> Обратный вызовaftercallback. -
settled<Функция> Обратный вызовsettledcallback.
-
- Возвращает: <Функция> Используется для отключения хуков
Обратные вызовы хука должны быть обычными функциями. Предоставление асинхронных функций приведет к ошибке, так как это создаст бесконечный цикл микрозадач.
Регистрирует функции, которые будут вызываться для различных событий жизненного цикла каждого промиса.
Обратные вызовы init()/before()/after()/settled() вызываются для соответствующих событий в течение жизненного цикла промиса.
Все обратные вызовы являются необязательными. Например, если нужно отслеживать только создание промисов, то необходимо передать только обратный вызов init. Подробности всех функций, которые можно передать в callbacks, указаны в разделе Обратные вызовы хуков.
Модули MJS
import { promiseHooks } from 'node:v8';
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
});
Модули CJS
const { promiseHooks } = require('node:v8');
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
}); Обратные вызовы хуков
Ключевые события в жизненном цикле промиса были разделены на четыре области: создание промиса, до/после вызова обработчика продолжения или вокруг ожидания, и когда промис разрешен или отклонен.
Хотя эти хуки похожи на хуки из async_hooks, им не хватает хука destroy. Другие типы асинхронных ресурсов обычно представляют сокеты или дескрипторы файлов, которые имеют отдельное состояние "закрыто" для выражения события жизненного цикла destroy, в то время как промисы остаются пригодными для использования, пока к ним может получить доступ код. Для отслеживания промисов используется отслеживание сборки мусора, но это очень дорого и они могут вообще не быть удалены из памяти.
Поскольку промисы являются асинхронными ресурсами, жизненный цикл которых отслеживается механизмом хуков промисов, обратные вызовы init(), before(), after(), и settled() не должны быть асинхронными функциями, так как они создают больше промисов, что приведет к бесконечному циклу.
Хотя этот API используется для передачи событий промисов в async_hooks, порядок между ними не определен. Оба API являются многопоточными и поэтому могут генерировать события в любом порядке относительно друг друга.
init(promise, parent)
Вызывается при создании промиса. Это не означает, что соответствующие события before/after будут происходить, только то, что такая возможность существует. Это произойдет, если промис создан, но никогда не получил продолжение.
before(promise)
-
promise<Промис>
Вызывается перед выполнением продолжения промиса. Это может быть в виде обработчиков then(), catch(), или finally() или возобновления await.
Обратный вызов before будет вызываться 0-N раз. Обратный вызов before обычно вызывается 0 раз, если для промиса никогда не было создано продолжение. Обратный вызов before может вызываться много раз в случае, когда от одного и того же промиса было сделано много продолжений.
after(promise)
-
promise<Промис>
Вызывается сразу после выполнения продолжения промиса. Это может быть после обработчика then(), catch(), или finally() или перед возобновлением await после другого await.
settled(promise)
-
promise<Промис>
Вызывается, когда промис получает значение разрешения или отклонения. Это может произойти синхронно в случае Promise.resolve() или Promise.reject().
API снимков начальной загрузки
Интерфейс 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])
-
callback<Функция> Обратный вызов, который будет вызван перед сериализацией. -
data<любое> Необязательные данные, которые будут переданы вcallbackпри его вызове.
Добавьте обратный вызов, который будет вызван, когда экземпляр Node.js собирается быть сериализован в снимок и завершить работу. Это можно использовать для освобождения ресурсов, которые не должны или не могут быть сериализованы, или для преобразования пользовательских данных в форму, более подходящую для сериализации.
v8.startupSnapshot.addDeserializeCallback(callback[, data])
-
callback<Функция> Обратный вызов, который будет вызван после десериализации снимка. -
data<любое> Необязательные данные, которые будут переданы вcallbackпри его вызове.
Добавьте обратный вызов, который будет вызван, когда экземпляр Node.js десериализован из снимка. callback и data (если предоставлены) будут сериализованы в снимок, они могут быть использованы для повторной инициализации состояния приложения или для повторного получения ресурсов, необходимых при запуске приложения из снимка.
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
-
callback<Функция> Обратный вызов, который будет вызван в качестве точки входа после десериализации снимка. -
data<любое> Необязательные данные, которые будут переданы вcallbackпри его вызове.
Это устанавливает точку входа приложения Node.js при десериализации из снимка. Это может быть вызвано только один раз в скрипте построения снимка. Если вызвано, десериализованному приложению больше не нужен дополнительный скрипт точки входа для запуска, и оно просто вызовет обратный вызов вместе с десериализованными данными (если предоставлены), в противном случае скрипт точки входа все еще должен быть предоставлен десериализованному приложению.
v8.startupSnapshot.isBuildingSnapshot()
- Возвращает: <логическое значение>
Возвращает true, если экземпляр Node.js запущен для построения снимка.
Класс: v8.GCProfiler
Этот API собирает данные GC в текущей нити.
new v8.GCProfiler()
Создает новый экземпляр класса v8.GCProfiler.
profiler.start()
Начать сбор данных GC.
profiler.stop()
Остановить сбор данных 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-v18.x/docs/api/v8.html