V8
ソースコード: lib/v8.js
node:v8
モジュールは、Node.js バイナリに組み込まれている V8 のバージョンに固有の API を公開します。次のようにアクセスできます。
const v8 = require('node:v8')
v8.cachedDataVersionTag()
追加されたバージョン: v8.0.0
- 戻り値: <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()
追加されたバージョン: v12.8.0
- 戻り値: <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([options])
[履歴]
バージョン | 変更 |
---|---|
v19.1.0 | ヒープスナップショットの設定オプションをサポート |
v11.13.0 | 追加: v11.13.0 |
options
<Object>戻り値: <stream.Readable> V8 ヒープスナップショットを含む Readable。
現在の V8 ヒープのスナップショットを生成し、JSON シリアル化された表現を読み取るために使用できる Readable Stream を返します。この JSON ストリーム形式は、Chrome DevTools などのツールで使用することを目的としています。JSON スキーマは文書化されておらず、V8 エンジンに固有です。そのため、スキーマは V8 のバージョンごとに変更される可能性があります。
ヒープスナップショットの作成には、スナップショット作成時のヒープサイズの約 2 倍のメモリが必要です。これにより、OOM キラーによってプロセスが終了するリスクがあります。
スナップショットの生成は同期操作であり、ヒープサイズに応じてイベントループをブロックします。
// ヒープスナップショットをコンソールに出力
const v8 = require('node:v8')
const stream = v8.getHeapSnapshot()
stream.pipe(process.stdout)
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
}
]
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
の値は、V8 の JavaScript オブジェクトによって現在使用されているバイト数です。これは実際に使用されているメモリであり、割り当てられているがまだ使用されていないメモリは含まれません。
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 フットプリント(常駐セットサイズ)は大きくなります。なぜなら、すべてのヒープページを継続的にタッチするため、オペレーティングシステムによってスワップアウトされる可能性が低くなるからです。
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.queryObjects(ctor[, options])
追加日時: v22.0.0, v20.13.0
ctor
<Function> ヒープ内の対象オブジェクトをフィルタリングするために、プロトタイプチェーンで検索に使用できるコンストラクタ。options
<undefined> | <Object>format
<string>'count'
の場合、一致したオブジェクトの数が返されます。'summary'
の場合、一致したオブジェクトのサマリー文字列を含む配列が返されます。
戻り値: {number|Array
これは、Chromium DevTools コンソールによって提供されるqueryObjects()
コンソール APIと似ています。完全なガベージコレクション後にヒープ内のプロトタイプチェーンに一致するコンストラクタを持つオブジェクトを検索するために使用できます。これは、メモリリーク回帰テストに役立ちます。予期しない結果を避けるために、ユーザーは、実装を制御していないコンストラクタ、またはアプリケーション内の他のパーティによって呼び出される可能性のあるコンストラクタに対して、この API を使用しないようにする必要があります。
偶発的なリークを回避するために、この API は検出されたオブジェクトへの生の参照を返しません。デフォルトでは、検出されたオブジェクトの数を返します。options.format
が'summary'
の場合、各オブジェクトの簡潔な文字列表現を含む配列を返します。この API で提供される可視性は、ヒープスナップショットが提供するものと似ていますが、ユーザーはシリアル化とパースのコストを節約し、検索中に直接対象オブジェクトをフィルタリングできます。
現在の実行コンテキストで作成されたオブジェクトのみが結果に含まれます。
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 prototype, so the child classes's prototype 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' }))
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 prototype, so the child classes's prototype 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 コマンドラインフラグをプログラムで設定するために使用できます。このメソッドは注意して使用する必要があります。VM の起動後に設定を変更すると、クラッシュやデータ損失など、予期しない動作が発生する可能性があります。あるいは、何も起こらない可能性もあります。
Node.js のバージョンで使用可能な V8 オプションは、node --v8-options
を実行することで確認できます。
使用方法:
// 1分間、stdoutにGCイベントを出力します。
const v8 = require('node:v8')
v8.setFlagsFromString('--trace_gc')
setTimeout(() => {
v8.setFlagsFromString('--notrace_gc')
}, 60e3)
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}
は Node.js プロセスの PID、{thread_id}
はwriteHeapSnapshot()
がメインの Node.js スレッドから呼び出された場合は0
、ワーカースレッドの場合はワーカースレッドの ID となります。options
<Object>戻り値: <string> スナップショットが保存されたファイル名。
現在の V8 ヒープのスナップショットを生成し、JSON ファイルに書き込みます。このファイルは、Chrome DevTools などのツールで使用することを目的としています。JSON スキーマは文書化されておらず、V8 エンジンに固有のものであり、V8 のバージョンごとに変更される可能性があります。
ヒープスナップショットは、単一の V8 isolate に固有です。ワーカースレッドを使用する場合、メインスレッドから生成されたヒープスナップショットには、ワーカーに関する情報が含まれません。逆も同様です。
ヒープスナップショットを作成するには、スナップショットを作成する時点でのヒープの約 2 倍のメモリが必要です。これにより、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)
追加: v18.10.0, v16.18.0
limit
<整数>
コマンドラインから--heapsnapshot-near-heap-limit
が既に設定されている場合、または API が複数回呼び出された場合は、この API は no-op です。limit
は正の整数である必要があります。詳細は--heapsnapshot-near-heap-limit
を参照してください。
シリアライゼーション API
シリアライゼーション API は、HTML 構造化クローンアルゴリズムと互換性のある方法で JavaScript 値をシリアライズする手段を提供します。
このフォーマットは後方互換性があります(つまり、ディスクに安全に保存できます)。等しい JavaScript 値は、異なるシリアライズされた出力になる可能性があります。
v8.serialize(value)
追加: v8.0.0
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)
上位と下位の 32 ビット部分に分割された生の 64 ビット符号なし整数を書き込みます。カスタムserializer._writeHostObject()
内で使用します。
serializer.writeDouble(value)
value
<number>
カスタムserializer._writeHostObject()
内での使用を目的とした、JS number
値の書き込み。
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
オブジェクトをシリアライズしようとする際に呼び出されるメソッドです。このSharedArrayBuffer
が既にシリアライズされている場合は同じ ID を使用し、オブジェクトの符号なし 32 ビット整数 ID を返す必要があります。デシリアライズ時には、この ID が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()
に渡します(SharedArrayBuffer
の場合はserializer._getSharedArrayBufferId()
からid
を返します)。
deserializer.getWireFormatVersion()
- 戻り値: <整数>
基盤となるワイヤフォーマットのバージョンを読み取ります。主に古いワイヤフォーマットバージョンを読み取るレガシーコードで役立つ可能性があります。.readHeader()
の前に呼び出されない場合があります。
deserializer.readUint32()
- 戻り値: <整数>
生の 32 ビット符号なし整数を取得して返します。カスタムdeserializer._readHostObject()
の内部で使用します。
deserializer.readUint64()
- 戻り値: <整数[]>
生の 64 ビット符号なし整数を取得し、2 つの 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
追加されたバージョン: v8.0.0
Serializer
のサブクラスで、TypedArray
(特に Buffer
)および DataView
オブジェクトをホストオブジェクトとしてシリアライズし、それらが参照している基盤となる ArrayBuffer
の一部のみを保存します。
クラス: v8.DefaultDeserializer
追加されたバージョン: v8.0.0
DefaultSerializer
によって書き込まれた形式に対応する Deserializer
のサブクラスです。
Promise フック
promiseHooks
インターフェースを使用して、Promise のライフサイクルイベントを追跡できます。すべての非同期アクティビティを追跡するには、async_hooks
を参照してください。このモジュールは内部的にこのモジュールを使用して、他の非同期リソースのイベントに加えて、Promise ライフサイクルイベントを生成します。リクエストコンテキスト管理については、AsyncLocalStorage
を参照してください。
import { promiseHooks } from 'node:v8'
// Promise によって生成される 4 つのライフサイクルイベントがあります。
// `init` イベントは、Promise の作成を表します。これは、`new Promise(...)` などの直接的な作成、または `then()` や `catch()` などの継続である可能性があります。非同期関数が呼び出されたり、`await` を実行したりする場合にも発生します。継続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)
追加: v17.1.0, v16.14.0
init
<Function> プロミスが作成されたときに呼び出される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)
追加: v17.1.0, v16.14.0
settled
<Function> プロミスが解決または拒否されたときに呼び出される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)
追加: v17.1.0, v16.14.0
before
<Function> プロミスの継続が実行される前に呼び出される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)
追加されたバージョン: v17.1.0, v16.14.0
after
<Function> プロミス継続実行後に呼び出される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)
追加されたバージョン: 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
に渡すことができるすべての関数の詳細は、フックコールバックセクションにあります。
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 のライフタイムにおける主要なイベントは、4 つの領域に分類されています。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 回呼び出されます。同じ Promise から多くの継続が行われた場合、before
コールバックは複数回呼び出される可能性があります。
after(promise)
promise
<Promise>
then()
、catch()
、finally()
ハンドラの後、または別のawait
の後のawait
の前に、Promise の継続実行の直後に呼び出されます。
settled(promise)
promise
<Promise>
Promise が解決値または拒否値を受け取ると呼び出されます。Promise.resolve()
またはPromise.reject()
の場合、同期的に発生することがあります。
スタートアップスナップショット API
追加されたバージョン: v18.6.0、v16.17.0
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()
// ディレクトリから一連のファイルを読み込み、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 は、スナップショット作成時にスナップショットスクリプトが配置される場所です。
const shelf = new BookShelf(__dirname, ['book1.en_US.txt', 'book1.es_ES.txt', 'book2.zh_CN.txt'])
assert(v8.startupSnapshot.isBuildingSnapshot())
// スナップショットのシリアル化時に、サイズを縮小するために書籍を圧縮します。
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf)
// スナップショットのデシリアル化時に、書籍を解凍します。
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf)
v8.startupSnapshot.setDeserializeMainFunction(shelf => {
// process.env と process.argv は、スナップショットのデシリアル化時に更新されます。
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
# スナップショットからデシリアライズされた book1.es_ES.txt の内容を出力します。 {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}
現在、ユーザーランドスナップショットからデシリアライズされたアプリケーションを再度スナップショットすることはできません。そのため、これらの API は、ユーザーランドスナップショットからデシリアライズされていないアプリケーションでのみ使用できます。
v8.startupSnapshot.addSerializeCallback(callback[, data])
追加されたバージョン: v18.6.0, v16.17.0
callback
<Function> シリアライズ前に呼び出されるコールバック。data
<any> コールバックが呼び出された際に渡されるオプションデータ。
Node.js インスタンスがスナップショットにシリアライズされ、終了しようとする際に呼び出されるコールバックを追加します。これは、シリアライズできない、またはすべきでないリソースを解放したり、ユーザーデータをシリアライズに適した形式に変換するために使用できます。
コールバックは追加された順序で実行されます。
v8.startupSnapshot.addDeserializeCallback(callback[, data])
追加されたバージョン: v18.6.0, v16.17.0
callback
<Function> スナップショットのデシリアライズ後に呼び出されるコールバック。data
<any> コールバックが呼び出された際に渡されるオプションデータ。
Node.js インスタンスがスナップショットからデシリアライズされた際に呼び出されるコールバックを追加します。callback
とdata
(指定されている場合)はスナップショットにシリアライズされ、アプリケーションの状態を再初期化したり、アプリケーションがスナップショットから再開された際にアプリケーションが必要とするリソースを再取得するために使用できます。
コールバックは追加された順序で実行されます。
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
追加されたバージョン: v18.6.0, v16.17.0
callback
<Function> スナップショットのデシリアライズ後にエントリポイントとして呼び出されるコールバック。data
<any> コールバックが呼び出された際に渡されるオプションデータ。
これは、スナップショットからデシリアライズされたときの Node.js アプリケーションのエントリポイントを設定します。これは、スナップショット構築スクリプトで一度だけ呼び出すことができます。呼び出された場合、デシリアライズされたアプリケーションは起動するための追加のエントリポイントスクリプトを必要としなくなり、デシリアライズされたデータ(指定されている場合)と共にコールバックを呼び出すだけです。そうでない場合、デシリアライズされたアプリケーションにはエントリポイントスクリプトを依然として提供する必要があります。
v8.startupSnapshot.isBuildingSnapshot()
追加日: v18.6.0, v16.17.0
- 戻り値: <boolean>
Node.js インスタンスがスナップショット作成のために実行されている場合、true
を返します。
クラス: 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
}
例を示します。
const { GCProfiler } = require('node:v8')
const profiler = new GCProfiler()
profiler.start()
setTimeout(() => {
console.log(profiler.stop())
}, 1000)