- assert断言
- async_hooks异步钩子
- async_hooks/context异步上下文
- buffer缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process子进程
- cluster集群
- CLI命令行
- console控制台
- Corepack核心包
- crypto加密
- crypto/webcrypto网络加密
- debugger调试器
- deprecation弃用
- dgram数据报
- diagnostics_channel诊断通道
- dns域名服务器
- domain域
- Error错误
- events事件触发器
- fs文件系统
- global全局变量
- http超文本传输协议
- http2超文本传输协议2.0
- https安全超文本传输协议
- inspector检查器
- Intl国际化
- module模块
- module/cjsCommonJS模块
- module/esmECMAScript模块
- module/package包模块
- net网络
- os操作系统
- path路径
- perf_hooks性能钩子
- permission权限
- policy安全策略
- process进程
- punycode域名代码
- querystring查询字符串
- readline逐行读取
- repl交互式解释器
- report诊断报告
- stream流
- stream/web网络流
- string_decoder字符串解码器
- test测试
- timers定时器
- tls安全传输层
- trace_events跟踪事件
- tty终端
- url网址
- util实用工具
- v8引擎
- vm虚拟机
- wasi网络汇编系统接口
- worker_threads工作线程
- zlib压缩
Node.js v18.15.0 文档
- Node.js 18.15.0
-
►
目录
- 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 引擎
-
►
索引
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS模块
- module/esm ECMAScript模块
- module/package 包模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- policy 安全策略
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- 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()
#
- 返回: <integer>
返回表示从 V8 版本、命令行标志、以及检测到的 CPU 特性派生的版本标签的整数。
这对于判断 vm.Script
cachedData
缓冲区是否与此 V8 实例兼容很有用。
console.log(v8.cachedDataVersionTag()); // 3947234607
// v8.cachedDataVersionTag() 返回的值源自
// V8 版本、命令行标志、以及检测到的 CPU 特性。
// 测试该值是否确实在切换标志时更新。
v8.setFlagsFromString('--allow_natives_syntax');
console.log(v8.cachedDataVersionTag()); // 183726201
v8.getHeapCodeStatistics()
#
- 返回: <Object>
获取堆中代码及其元数据的统计信息,请参阅 V8 GetHeapCodeAndMetadataStatistics
API。
返回具有以下属性的对象:
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,
}
v8.getHeapSnapshot()
#
- 返回: <stream.Readable> 包含 V8 堆快照的可读流
生成当前 V8 堆的快照并返回可用于读取 JSON 序列化表示的可读流。 此 JSON 流格式旨在与 Chrome 开发者工具等工具一起使用。 JSON 模式未记录并且特定于 V8 引擎。 因此,模式可能会从 V8 的一个版本更改为下一个版本。
创建堆快照需要的内存大约是创建快照时堆大小的两倍。 这会导致 OOM 杀手终止进程的风险。
生成快照是一个同步的操作,它会根据堆大小在一段时间内阻塞事件循环。
// 打印堆快照到控制台
const v8 = require('node:v8');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout);
v8.getHeapSpaceStatistics()
#
- 返回: <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
}
]
v8.getHeapStatistics()
#
- 返回: <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>
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
<string>
v8.setFlagsFromString()
方法可用于以编程方式设置 V8 命令行标志。
此方法需谨慎使用。
在虚拟机启动后更改设置可能会导致不可预测的行为,包括崩溃和数据丢失;或者它可能只是什么都不做。
可以通过运行 node --v8-options
来确定 Node.js 版本可用的 V8 选项。
用法:
// 将 GC 事件打印到标准输出一分钟。
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,当writeHeapSnapshot()
从 Node.js 主线程调用时,{thread_id}
将是0
或工作线程的 id。- 返回: <string> 保存快照的文件名。
生成当前 V8 堆的快照并将其写入 JSON 文件。 此文件旨在与 Chrome 开发者工具等工具一起使用 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}`);
// 现在获取主线程的堆转储。
console.log(`main thread heapdump: ${writeHeapSnapshot()}`);
});
// 告诉工作进程创建堆转储。
worker.postMessage('heapdump');
} else {
parentPort.once('message', (message) => {
if (message === 'heapdump') {
// 为工作进程生成堆转储,
// 并将文件名返回给父进程。
parentPort.postMessage(writeHeapSnapshot());
}
});
}
v8.setHeapSnapshotNearHeapLimit(limit)
#
limit
<integer>
如果 --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
<Buffer> | <TypedArray> | <DataView>serialize()
返回的缓冲区。
使用带有默认选项的 DefaultDeserializer
从缓冲区读取 JS 值。
v8.Serializer
类#
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)
#
写入原始的 64 位无符号整数,分成高和低 32 位部分。
用于自定义的 serializer._writeHostObject()
内部。
serializer.writeDouble(value)
#
value
<number>
写入 JS number
值。
用于自定义的 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 位整数 ID,如果此 SharedArrayBuffer
已被序列化,则使用相同的 ID。
当反序列化时,此 ID 会传给 deserializer.transferArrayBuffer()
。
如果对象无法序列化,则应抛出异常。
此方法不存在于 Serializer
类本身,但可以由子类提供。
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
#
flag
<boolean> 默认值:false
指示是否将 TypedArray
和 DataView
对象视为宿主对象,即将它们传给 serializer._writeHostObject()
。
v8.Deserializer
类#
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()
(或者在 SharedArrayBuffer
的情况下从 serializer._getSharedArrayBufferId()
返回 id
)。
deserializer.getWireFormatVersion()
#
- 返回: <integer>
读取底层有线格式版本。
可能主要用于读取旧的有线格式版本的遗留代码
不能在 .readHeader()
之前调用。
deserializer.readUint32()
#
- 返回: <integer>
读取原始的 32 位无符号整数并返回。
用于自定义的 deserializer._readHostObject()
内部。
deserializer.readUint64()
#
- 返回: <integer[]>
读取原始的 64 位无符号整数并将其作为具有两个 32 位无符号整数条目的数组 [hi, lo]
返回。
用于自定义的 deserializer._readHostObject()
内部。
deserializer.readDouble()
#
- 返回: <number>
读取 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
类#
DefaultSerializer
所写格式对应的 Deserializer
子类。
Promise 钩子#
promiseHooks
接口可用于跟踪 promise 生命周期事件。
要跟踪所有的异步活动,则参阅 async_hooks
,其在内部使用此模块生成 promise 生命周期事件以及其他异步资源的事件。
请求的上下文管理参阅 AsyncLocalStorage
。
import { promiseHooks } from 'node:v8';
// promise 产生了四个生命周期事件:
// `init` 事件代表了 promise 的创建。
// 这可以是直接创建,例如使用 `new Promise(...)`,
// 或者是继续,例如 `then()` 或 `catch()`。
// 每当调用异步函数或执行“等待”时,也会发生这种情况。
// 如果创建了继续 promise,则 `parent` 将是它作为继续的 promise。
function init(promise, parent) {
console.log('a promise was created', { promise, parent });
}
// `settled` 事件在 promise 收到解决或拒绝值时发生。
// 这可能会同步地发生,
// 例如在非 promise 输入上使用 `Promise.resolve()` 时。
function settled(promise) {
console.log('a promise resolved or rejected', { promise });
}
// `before` 事件在 `then()` 或 `catch()` 句柄运行
// 或 `await` 恢复执行之前立即运行。
function before(promise) {
console.log('a promise is about to call a then handler', { promise });
}
// `after` 事件在 `then()` 句柄运行之后
// 或 `await` 从另一个句柄恢复之后立即运行。
function after(promise) {
console.log('a promise is done calling a then handler', { promise });
}
// 生命周期钩子可以单独启动和停止
const stopWatchingInits = promiseHooks.onInit(init);
const stopWatchingSettleds = promiseHooks.onSettled(settled);
const stopWatchingBefores = promiseHooks.onBefore(before);
const stopWatchingAfters = promiseHooks.onAfter(after);
// 或者它们可以分组启动和停止
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
});
// 要停止钩子,则调用创建时返回的函数。
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> 要注册的钩子回调init
<Function>init
回调。before
<Function>before
回调。after
<Function>after
回调。settled
<Function>settled
回调。
- 返回: <Function> 用于禁用钩子 钩子回调必须是普通函数。 提供异步函数会抛出异常,因为它会产生无限的微任务循环。
注册要为每个 promise 的不同生命周期事件调用的函数。
回调 init()
/before()
/after()
/settled()
在 promise 的生命周期内为各个事件调用。
所有回调都是可选的。
例如,如果只需要跟踪 promise 的创建,则只需要传入 init
回调。
可以传给 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 的创建、调用继续句柄之前/之后或 await 前后,以及当 promise 解决或拒绝时。
虽然这些钩子与 async_hooks
的钩子相似,但它们缺少 destroy
钩子。
其他类型的异步资源通常表示套接字或文件描述符,它们具有不同的“关闭”状态来表达 destroy
生命周期事件,而只要代码仍然可以访问它们,则 promise 就仍然可用。
垃圾收集跟踪用于使 promise 适合 async_hooks
事件模型,但是这种跟踪非常昂贵,而且它们甚至不一定会被垃圾收集。
因为 promise 是异步的资源,其生命周期通过 promise 钩子机制进行跟踪,所以 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 次。
before
回调可能会在同一个 promise 进行了许多继续的情况下被多次调用。
after(promise)
#
promise
<Promise>
在 promise 继续执行后立即调用。
这可能在 then()
、catch()
或 finally()
句柄之后,或者在另一个 await
之后的 await
之前。
settled(promise)
#
promise
<Promise>
当 promise 收到解决或拒绝值时调用。
这可能在 Promise.resolve()
或 Promise.reject()
的情况下同步地发生。
启动快照 API#
v8.startupSnapshot
接口可用于为自定义启动快照添加序列化和反序列化钩子。
目前启动快照只能从源代码构建到 Node.js 二进制文件中。
$ cd /path/to/node
$ ./configure --node-snapshot-main=entry.js
$ make node
# 此二进制文件包含 entry.js 的执行结果
$ out/Release/node
在上面的例子中,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 {
isBuildingSnapshot,
addSerializeCallback,
addDeserializeCallback,
setDeserializeMainFunction,
} = require('node:v8').startupSnapshot;
const filePath = path.resolve(__dirname, '../x1024.txt');
const storage = {};
assert(isBuildingSnapshot());
addSerializeCallback(({ filePath }) => {
storage[filePath] = zlib.gzipSync(fs.readFileSync(filePath));
}, { filePath });
addDeserializeCallback(({ filePath }) => {
storage[filePath] = zlib.gunzipSync(storage[filePath]);
}, { filePath });
setDeserializeMainFunction(({ filePath }) => {
console.log(storage[filePath].toString());
}, { filePath });
生成的二进制文件将在启动期间简单地打印从快照反序列化的数据:
$ out/Release/node
# 打印 ./test/fixtures/x1024.txt 的内容
目前该 API 仅适用于从默认快照启动的 Node.js 实例,即从用户端快照反序列化的应用程序无法再次使用这些 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 应用程序的入口点。 在快照构建脚本中只能调用一次。 如果被调用,反序列化应用程序不再需要额外的入口点脚本来启动,并且只需调用回调以及反序列化数据(如果提供),否则仍需要向反序列化应用程序提供入口点脚本。
v8.startupSnapshot.isBuildingSnapshot()
#
- 返回: <boolean>
如果运行 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);