- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲(Buffer)
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入 Node环境
- 子进程(Child processes)
- 集群(Cluster)
- 命令行选项
- 控制台(Console)
- 核心包(Corepack)
- 加密(Crypto)
- 调试器(Debugger)
- 已弃用的 API
- 诊断通道(Diagnostics Channel)
- 域名系统(DNS)
- 域(Domain)
- 错误(Errors)
- 事件(Events)
- 文件系统(File system)
- 全局变量(Globals)
- HTTP
- HTTP/2
- HTTPS
- 检查器(Inspector)
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:packages 模块
- 网络(Net)
- 系统(OS)
- 路径(Path)
- 性能挂钩(Performance hooks)
- 性能挂钩(Permissions)
- 进程(Process)
- Punycode 国际化域名编码
- 查询字符串(Query strings)
- 命令行库(Readline)
- REPL 交互式编程环境
- 诊断报告
- 单个可执行应用程序
- Stream 流
- 字符串解码器
- 单元测试
- 定时器(Timers)
- 传输层安全/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用程序
- V8
- 虚拟机
- WebAssembly
- Web加密 API(Web Crypto API)
- 网络流 API(Web Streams API)
- 工作线程(Worker threads)
- zlib
Node.js v18.18.2 文档
- Node.js v18.18.2
-
►
目录
- V8
v8.cachedDataVersionTag()
v8.getHeapCodeStatistics()
v8.getHeapSnapshot()
v8.getHeapSpaceStatistics()
v8.getHeapStatistics()
v8.setFlagsFromString(flags)
v8.stopCoverage()
v8.takeCoverage()
v8.writeHeapSnapshot([filename])
v8.setHeapSnapshotNearHeapLimit(limit)
- 序列化API
v8.serialize(value)
v8.deserialize(buffer)
- 类:
v8.Serializer
new Serializer()
serializer.writeHeader()
serializer.writeValue(value)
serializer.releaseBuffer()
serializer.transferArrayBuffer(id, arrayBuffer)
serializer.writeUint32(value)
serializer.writeUint64(hi, lo)
serializer.writeDouble(value)
serializer.writeRawBytes(buffer)
serializer._writeHostObject(object)
serializer._getDataCloneError(message)
serializer._getSharedArrayBufferId(sharedArrayBuffer)
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
- 类:
v8.Deserializer
new Deserializer(buffer)
deserializer.readHeader()
deserializer.readValue()
deserializer.transferArrayBuffer(id, arrayBuffer)
deserializer.getWireFormatVersion()
deserializer.readUint32()
deserializer.readUint64()
deserializer.readDouble()
deserializer.readRawBytes(length)
deserializer._readHostObject()
- 类:
v8.DefaultSerializer
- 类:
v8.DefaultDeserializer
- Promise 挂钩
- 启动快照API
- 类:
v8.GCProfiler
- V8
-
►
索引
- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲(Buffer)
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入 Node环境
- 子进程(Child processes)
- 集群(Cluster)
- 命令行选项
- 控制台(Console)
- 核心包(Corepack)
- 加密(Crypto)
- 调试器(Debugger)
- 已弃用的 API
- 诊断通道(Diagnostics Channel)
- 域名系统(DNS)
- 域(Domain)
- 错误(Errors)
- 事件(Events)
- 文件系统(File system)
- 全局变量(Globals)
- HTTP
- HTTP/2
- HTTPS
- 检查器(Inspector)
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:packages 模块
- 网络(Net)
- 系统(OS)
- 路径(Path)
- 性能挂钩(Performance hooks)
- 性能挂钩(Permissions)
- 进程(Process)
- Punycode
- Query strings
- 命令行库(Readline)
- REPL 交互式编程环境
- Report
- Single executable applications
- Stream
- String decoder
- Test runner
- Timers
- TLS/SSL
- Trace events
- TTY
- UDP/datagram
- URL
- Utilities
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- Worker threads
- Zlib
- ► 其他版本
- ► 选项
目录
- V8
v8.cachedDataVersionTag()
v8.getHeapCodeStatistics()
v8.getHeapSnapshot()
v8.getHeapSpaceStatistics()
v8.getHeapStatistics()
v8.setFlagsFromString(flags)
v8.stopCoverage()
v8.takeCoverage()
v8.writeHeapSnapshot([filename])
v8.setHeapSnapshotNearHeapLimit(limit)
- 序列化API
v8.serialize(value)
v8.deserialize(buffer)
- 类:
v8.Serializer
new Serializer()
serializer.writeHeader()
serializer.writeValue(value)
serializer.releaseBuffer()
serializer.transferArrayBuffer(id, arrayBuffer)
serializer.writeUint32(value)
serializer.writeUint64(hi, lo)
serializer.writeDouble(value)
serializer.writeRawBytes(buffer)
serializer._writeHostObject(object)
serializer._getDataCloneError(message)
serializer._getSharedArrayBufferId(sharedArrayBuffer)
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
- 类:
v8.Deserializer
new Deserializer(buffer)
deserializer.readHeader()
deserializer.readValue()
deserializer.transferArrayBuffer(id, arrayBuffer)
deserializer.getWireFormatVersion()
deserializer.readUint32()
deserializer.readUint64()
deserializer.readDouble()
deserializer.readRawBytes(length)
deserializer._readHostObject()
- 类:
v8.DefaultSerializer
- 类:
v8.DefaultDeserializer
- Promise 挂钩
- 启动快照API
- 类:
v8.GCProfiler
V8#
源代码: lib/v8.js
node:v8
模块公开特定于
Node.js 二进制文件中内置的V8版本的 API。可以使用以下方式访问它:
const v8 = require('node:v8');
v8.cachedDataVersionTag()
#
- 返回:<整数>
返回一个整数,表示从 V8 版本、命令行标志和检测到的 CPU 功能派生的版本标记。这对于确定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
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,
}
v8.getHeapSnapshot()
#
- 返回:<stream.Readable>包含 V8 堆快照的可读流
生成当前 V8 堆的快照并返回可用于读取 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);
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
}
]
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
}
v8.setFlagsFromString(flags)
#
flags
<字符串>
v8.setFlagsFromString()
方法可用于以编程方式设置 V8 命令行标志。此方法应谨慎使用。VM 启动后更改设置可能会导致不可预测的行为,包括崩溃和数据丢失;或者它可能什么也不做。
Node.js 版本可用的 V8 选项可以通过运行
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);
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
<string>保存 V8 堆快照的文件路径。如果未指定,将生成模式为'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'
的文件名,其中{pid}
为 Node.js 进程的 PID,{thread_id}
为0
当从主 Node.js 线程或工作线程的 ID 调用writeHeapSnapshot()
时。- 返回:<string>保存快照的文件名。
生成当前 V8 堆的快照并将其写入 JSON 文件。该文件旨在与 Chrome DevTools 等工具一起使用。JSON 架构未记录且特定于 V8 引擎,并且可能会从一个版本的 V8 更改为下一版本。
堆快照特定于单个 V8 隔离。当使用 工作线程时,从主线程生成的堆快照将不包含有关工作线程的任何信息,反之亦然。
创建堆快照需要的内存大约是创建快照时堆大小的两倍。这会导致 OOM 杀手终止进程的风险。
生成快照是一个同步操作,它会根据堆大小阻塞事件循环一段时间。
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());
}
});
}
v8.setHeapSnapshotNearHeapLimit(limit)
#
limit
<整数>
如果已从命令行设置--heapsnapshot-near-heap-limit
或多次调用 API,则该 API为无操作。limit
必须是正整数。请参阅--heapsnapshot-near-heap-limit
了解更多信息。
序列化API#
序列化 API 提供了以与HTML 结构化克隆算法兼容的方式序列化 JavaScript 值的方法。
该格式是向后兼容的(即可以安全地存储到磁盘)。相同的 JavaScript 值可能会导致不同的序列化输出。
v8.serialize(value)
#
使用DefaultSerializer
将value
序列化到缓冲区中。
当尝试序列化需要大于buffer.constants.MAX_LENGTH
的缓冲区的大对象时,将抛出ERR_BUFFER_TOO_LARGE
。
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
<integer> 32 位无符号整数。arrayBuffer
<ArrayBuffer>一个ArrayBuffer
实例。
将ArrayBuffer
标记为将其内容传输到带外。将反序列化上下文中
相应的ArrayBuffer
传递给deserializer.transferArrayBuffer()
。
serializer.writeUint32(value)
#
value
<整数>
写入原始 32 位无符号整数。用于自定义serializer._writeHostObject()
内部。
serializer.writeUint64(hi, lo)
#
写入一个原始 64 位无符号整数,分为高 32 位部分和低 32 位部分。用于自定义serializer._writeHostObject()
内部。
serializer.writeDouble(value)
#
value
<数字>
写入 JS number
值。用于自定义serializer._writeHostObject()
内部。
serializer.writeRawBytes(buffer)
#
将原始字节写入序列化器的内部缓冲区。解串器需要一种方法来计算缓冲区的长度。用于自定义serializer._writeHostObject()
内部。
serializer._writeHostObject(object)
#
object
<对象>
调用此方法来编写某种主机对象,即由本机 C++ 绑定创建的对象。如果无法序列化object
,则应抛出适当的异常。
此方法不存在于Serializer
类本身中,但可以由子类提供。
serializer._getDataCloneError(message)
#
message
<字符串>
调用此方法会生成错误对象,当无法克隆对象时将抛出该错误对象。
此方法默认为Error
构造函数,可以在子类上重写。
serializer._getSharedArrayBufferId(sharedArrayBuffer)
#
sharedArrayBuffer
<SharedArrayBuffer>
当序列化器要序列化
SharedArrayBuffer
对象时,会调用此方法。它必须返回对象的无符号 32 位整数 ID,如果此SharedArrayBuffer
已被序列化,则使用相同的 ID。反序列化时,此 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
<integer> 32 位无符号整数。arrayBuffer
<ArrayBuffer> | <SharedArrayBuffer>一个ArrayBuffer
实例。
将ArrayBuffer
标记为将其内容传输到带外。将序列化上下文中
相应的ArrayBuffer
传递给serializer.transferArrayBuffer()
(或者在 SharedArrayBuffer
的情况下从
serializer._getSharedArrayBufferId()
返回 id
s)。
deserializer.getWireFormatVersion()
#
- 返回:<整数>
读取底层有线格式版本。可能对读取旧有线格式版本的遗留代码很有用。不得在
.readHeader()
之前调用。
deserializer.readUint32()
#
- 返回:<整数>
读取原始 32 位无符号整数并返回它。用于自定义deserializer._readHostObject()
内部。
deserializer.readUint64()
#
- 返回:<整数[]>
读取原始 64 位无符号整数并将其作为包含
两个 32 位无符号整数条目的数组[hi, lo]
返回。用于自定义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
编写的格式
。
Promise 挂钩#
promiseHooks
接口可用于跟踪 Promise 生命周期事件。要跟踪所有异步事件,请参阅async_hooks
,它在内部使用此模块生成 Promise 生命周期事件以及其他异步资源的事件。有关请求上下文管理,请参阅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();
promiseHooks.onInit(init)
#
init
<Function>创建 Promise 时调用的init
回调。- 返回:<Function>调用以停止钩子。
init
挂钩必须是普通函数。提供异步函数会抛出异常,因为它会产生无限的微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onInit((promise, parent) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onInit((promise, parent) => {});
promiseHooks.onSettled(settled)
#
settled
<Function>当 Promise 得到解决或拒绝时调用的settled
回调。- 返回:<Function>调用以停止钩子。
settled
挂钩必须是普通函数。提供异步函数会抛出异常,因为它会产生无限的微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onSettled((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onSettled((promise) => {});
promiseHooks.onBefore(before)
#
before
<Function>在执行 Promise 延续之前调用的before
回调。- 返回:<Function>调用以停止钩子。
before
挂钩必须是普通函数。提供异步函数会抛出异常,因为它会产生无限的微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onBefore((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onBefore((promise) => {});
promiseHooks.onAfter(after)
#
after
<Function>在执行 Promise 延续后调用的after
回调。- 返回:<Function>调用以停止钩子。
after
挂钩必须是普通函数。提供异步函数会抛出异常,因为它会产生无限的微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onAfter((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onAfter((promise) => {});
promiseHooks.createHook(callbacks)
#
callbacks
<Object>要注册的 Hook回调init
<Function> { { {0306}}}回调。before
<Function> { { {0308}}}回调。after
<Function> { { {0310}}}回调。settled
<Function> { { {0312}}}回调。
- 返回:<Function>用于禁用钩子
钩子回调必须是普通函数。提供异步函数会抛出异常,因为它会产生无限的微任务循环。
注册为每个 Promise 的不同生命周期事件调用的函数。
在 Promise 生命周期内,针对相应事件调用回调init()
/ before()
/ after()
/ settled()
。
所有回调都是可选的。例如,如果只需要跟踪 Promise 创建,则只需要传递init
回调。可以传递给callbacks
的所有函数的详细信息位于
Hook Callbacks部分。
import { promiseHooks } from 'node:v8';
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
});
const { promiseHooks } = require('node:v8');
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
});
钩子回调#
Promise 生命周期中的关键事件分为四个区域:Promise 的创建、调用延续处理程序之前/之后或等待期间以及 Promise 何时解析或拒绝。
虽然这些钩子与async_hooks
的钩子类似,但它们缺少
destroy
钩子。其他类型的异步资源通常表示套接字或文件描述符,它们具有明显的“关闭”状态来表示destroy
生命周期事件,而只要代码仍然可以访问它们, Promise 就保持可用。垃圾收集跟踪用于使 Promise 适合
async_hooks
事件模型,但是这种跟踪非常昂贵,而且它们可能不一定会被垃圾收集。
由于 Promise 是异步资源,其生命周期通过 Promise hooks 机制进行跟踪,因此init()
、before()
、after()
和
settled()
回调必须不是异步函数,因为它们创建了更多的 Promise ,这会产生无限循环。
虽然此 API 用于将 Promise 事件提供给async_hooks
,但两者之间的顺序是未定义的。这两个 API 都是多租户的,因此可以按彼此相关的任何顺序生成事件。
init(promise, parent)
#
在构造 Promise 时调用。这并不意味着相应的
before
/ after
事件将会发生,只是存在这种可能性。如果创建了一个 Promise 但没有得到延续,就会发生这种情况。
before(promise)
#
promise
< Promise >
在 Promise 延续执行之前调用。这可以采用
then()
、catch()
或finally()
处理程序或await
恢复的形式。
before
回调将被调用 0 到 N 次。如果没有对 Promise 进行任何延续,则before
回调通常会被调用 0 次。如果同一个 Promise 进行了多次延续,则before
回调可能会被多次调用。
after(promise)
#
promise
< Promise >
在 Promise 延续执行后立即调用。这可能位于
then()
、catch()
或finally()
处理程序之后,或者位于另一个
await
之后的 await
之前。
settled(promise)
#
promise
< 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
在上面的示例中,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);
生成的二进制文件将使用已启动进程的刷新的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.
目前,从用户态快照反序列化的应用程序无法再次进行快照,因此这些 API 仅适用于未从用户态快照反序列化的应用程序。
v8.startupSnapshot.addSerializeCallback(callback[, data])
#
callback
<Function>在序列化之前调用的回调。data
<any>调用时将传递给callback
的可选数据。
添加一个回调,当 Node.js 实例即将序列化为快照并退出时将调用该回调。这可以用来释放不应该或不能序列化的资源,或者将用户数据转换成更适合序列化的形式。
v8.startupSnapshot.addDeserializeCallback(callback[, data])
#
callback
<Function>快照反序列化后调用的回调。data
<any>调用时将传递给callback
的可选数据。
添加一个回调,当从快照反序列化 Node.js 实例时将调用该回调。callback
和data
(如果提供)将被序列化到快照中,它们可用于重新初始化应用程序的状态或重新获取应用程序所占用的资源从快照重新启动应用程序时需要。
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
#
callback
<Function>快照反序列化后作为入口点调用的回调。data
<any>调用时将传递给callback
的可选数据。
当从快照反序列化 Node.js 应用程序时,这会设置 Node.js 应用程序的入口点。这只能在快照构建脚本中调用一次。如果调用,反序列化应用程序不再需要额外的入口点脚本来启动,并且只需调用回调以及反序列化数据(如果提供),否则仍然需要向反序列化应用程序提供入口点脚本。
v8.startupSnapshot.isBuildingSnapshot()
#
- 返回:<布尔值>
如果运行 Node.js 实例来构建快照,则返回 true。
类: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
}
这是一个例子。
const { GCProfiler } = require('v8');
const profiler = new GCProfiler();
profiler.start();
setTimeout(() => {
console.log(profiler.stop());
}, 1000);