V8
Código fuente: lib/v8.js
El módulo node:v8
expone APIs que son específicas de la versión de V8 integrada en el binario de Node.js. Se puede acceder usando:
const v8 = require('node:v8');
v8.cachedDataVersionTag()
Agregado en: v8.0.0
- Regresa: <integer>
Regresa un entero que representa una etiqueta de versión derivada de la versión de V8, los flags de línea de comandos y las características detectadas de la CPU. Esto es útil para determinar si un búfer cachedData
de vm.Script
es compatible con esta instancia de V8.
console.log(v8.cachedDataVersionTag()); // 3947234607
// El valor regresado por v8.cachedDataVersionTag() se deriva de la versión
// de V8, los flags de línea de comandos y las características detectadas de la CPU.
// Prueba que el valor se actualice cuando los flags se activen/desactiven.
v8.setFlagsFromString('--allow_natives_syntax');
console.log(v8.cachedDataVersionTag()); // 183726201
v8.getHeapCodeStatistics()
Agregado en: v12.8.0
- Regresa: <Object>
Obtén estadísticas sobre el código y sus metadatos en el heap, mira la API GetHeapCodeAndMetadataStatistics
de V8. Regresa un objeto con las siguientes propiedades:
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])
[Historial]
Versión | Cambios |
---|---|
v19.1.0 | Soporte para opciones para configurar la captura de montón. |
v11.13.0 | Añadido en: v11.13.0 |
options
<Objeto>exposeInternals
<booleano> Si es true, expone los elementos internos en la captura del montón. Predeterminado:false
.exposeNumericValues
<booleano> Si es true, expone los valores numéricos en campos artificiales. Predeterminado:false
.
Devuelve: <stream.Readable> Un Readable que contiene la captura de montón de V8.
Genera una captura del montón V8 actual y devuelve un flujo Readable que se puede utilizar para leer la representación serializada JSON. Este formato de flujo JSON está destinado a ser utilizado con herramientas como Chrome DevTools. El esquema JSON no está documentado y es específico del motor V8. Por lo tanto, el esquema puede cambiar de una versión de V8 a la siguiente.
Crear una captura de montón requiere una memoria aproximadamente dos veces el tamaño del montón en el momento en que se crea la captura. Esto resulta en el riesgo de que los terminadores OOM terminen el proceso.
Generar una captura es una operación síncrona que bloquea el bucle de eventos durante una duración que depende del tamaño del montón.
// Imprime la captura del montón en la consola
const v8 = require('node:v8');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout);
v8.getHeapSpaceStatistics()
[Historial]
Versión | Cambios |
---|---|
v7.5.0 | Soporte para valores que exceden el rango de enteros sin signo de 32 bits. |
v6.0.0 | Añadido en: v6.0.0 |
- Devuelve: <Objeto[]>
Devuelve estadísticas sobre los espacios de montón de V8, es decir, los segmentos que componen el montón de V8. Ni el orden de los espacios de montón, ni la disponibilidad de un espacio de montón pueden garantizarse ya que las estadísticas se proporcionan a través de la función V8 GetHeapSpaceStatistics
y puede cambiar de una versión de V8 a la siguiente.
El valor devuelto es una matriz de objetos que contienen las siguientes propiedades:
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()
[Historial]
Versión | Cambios |
---|---|
v7.5.0 | Soporta valores que exceden el rango entero sin signo de 32 bits. |
v7.2.0 | Se agregaron malloced_memory , peak_malloced_memory y does_zap_garbage . |
v1.0.0 | Agregado en: v1.0.0 |
- Devuelve: <Objeto>
Devuelve un objeto con las siguientes propiedades:
total_heap_size
<número>total_heap_size_executable
<número>total_physical_size
<número>total_available_size
<número>used_heap_size
<número>heap_size_limit
<número>malloced_memory
<número>peak_malloced_memory
<número>does_zap_garbage
<número>number_of_native_contexts
<número>number_of_detached_contexts
<número>total_global_handles_size
<número>used_global_handles_size
<número>external_memory
<número>
total_heap_size
El valor de total_heap_size es el número de bytes que V8 ha asignado para el heap. Esto puede crecer si used_heap necesita más memoria.
total_heap_size_executable
El valor de total_heap_size_executable es la porción del heap que puede contener código ejecutable, en bytes. Esto incluye la memoria utilizada por el código compilado con JIT y cualquier memoria que deba mantenerse ejecutable.
total_physical_size
El valor de total_physical_size es la memoria física real utilizada por el heap de V8, en bytes. Esta es la cantidad de memoria que se confirma (o en uso) en lugar de reservada.
total_available_size
El valor de total_available_size es el número de bytes de memoria disponibles para el heap de V8. Este valor representa cuánta memoria más puede usar V8 antes de exceder el límite del heap.
used_heap_size
El valor de used_heap_size es el número de bytes que están utilizando actualmente los objetos JavaScript de V8. Esta es la memoria real en uso y no incluye la memoria que se ha asignado pero aún no se ha utilizado.
heap_size_limit
El valor de heap_size_limit es el tamaño máximo del heap de V8, en bytes (ya sea el límite predeterminado, determinado por los recursos del sistema, o el valor pasado a la opción --max_old_space_size
).
malloced_memory
El valor de malloced_memory es el número de bytes asignados a través de malloc
por V8.
peak_malloced_memory
El valor de peak_malloced_memory es el número máximo de bytes asignados a través de malloc
por V8 durante la vida útil del proceso.
does_zap_garbage
es un booleano 0/1, que indica si la opción --zap_code_space
está habilitada o no. Esto hace que V8 sobrescriba la basura del montón con un patrón de bits. La huella RSS (tamaño del conjunto residente) se hace más grande porque toca continuamente todas las páginas del montón y eso hace que sea menos probable que el sistema operativo las intercambie.
number_of_native_contexts
El valor de native_context es el número de contextos de nivel superior actualmente activos. El aumento de este número con el tiempo indica una fuga de memoria.
number_of_detached_contexts
El valor de detached_context es el número de contextos que se separaron y aún no se recolectaron como basura. Que este número sea distinto de cero indica una posible fuga de memoria.
total_global_handles_size
El valor de total_global_handles_size es el tamaño total de la memoria de los identificadores globales de V8.
used_global_handles_size
El valor de used_global_handles_size es el tamaño de la memoria utilizada de los identificadores globales de V8.
external_memory
El valor de external_memory es el tamaño de la memoria de los búferes de matriz y las cadenas externas.
{
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])
Agregado en: v22.0.0, v20.13.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1.1 - Desarrollo activo
ctor
<Function> El constructor que se puede utilizar para buscar en la cadena de prototipos para filtrar los objetos objetivo en el montón.options
<undefined> | <Object>format
<string> Si es'count'
, se devuelve el recuento de objetos coincidentes. Si es'summary'
, se devuelve un array con cadenas de resumen de los objetos coincidentes.
Devuelve: {number|Array
Esto es similar a la queryObjects()
API de la consola proporcionada por la consola de Chromium DevTools. Se puede utilizar para buscar objetos que tienen el constructor coincidente en su cadena de prototipos en el montón después de una recolección completa de basura, lo que puede ser útil para las pruebas de regresión de fugas de memoria. Para evitar resultados sorprendentes, los usuarios deben evitar el uso de esta API en constructores cuya implementación no controlan, o en constructores que pueden ser invocados por otras partes en la aplicación.
Para evitar fugas accidentales, esta API no devuelve referencias sin procesar a los objetos encontrados. De forma predeterminada, devuelve el recuento de los objetos encontrados. Si options.format
es 'summary'
, devuelve un array que contiene representaciones de cadena breves para cada objeto. La visibilidad proporcionada en esta API es similar a la que proporciona la instantánea del montón, mientras que los usuarios pueden ahorrar el costo de la serialización y el análisis y filtrar directamente los objetos objetivo durante la búsqueda.
Solo los objetos creados en el contexto de ejecución actual se incluyen en los resultados.
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)
Añadido en: v1.0.0
flags
<string>
El método v8.setFlagsFromString()
se puede usar para establecer indicadores de línea de comandos de V8 de forma programática. Este método se debe utilizar con precaución. Cambiar la configuración después de que la VM se haya iniciado puede provocar un comportamiento impredecible, incluidos bloqueos y pérdida de datos; o simplemente puede que no haga nada.
Las opciones de V8 disponibles para una versión de Node.js se pueden determinar ejecutando node --v8-options
.
Uso:
// Imprime eventos de GC en stdout durante un minuto.
const v8 = require('node:v8');
v8.setFlagsFromString('--trace_gc');
setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
v8.stopCoverage()
Añadido en: v15.1.0, v14.18.0, v12.22.0
El método v8.stopCoverage()
permite al usuario detener la recopilación de cobertura iniciada por NODE_V8_COVERAGE
, para que V8 pueda liberar los registros de recuento de ejecución y optimizar el código. Esto se puede usar junto con v8.takeCoverage()
si el usuario desea recopilar la cobertura bajo demanda.
v8.takeCoverage()
Añadido en: v15.1.0, v14.18.0, v12.22.0
El método v8.takeCoverage()
permite al usuario escribir la cobertura iniciada por NODE_V8_COVERAGE
en el disco bajo demanda. Este método se puede invocar varias veces durante la vida útil del proceso. Cada vez que se restablece el contador de ejecución y se escribe un nuevo informe de cobertura en el directorio especificado por NODE_V8_COVERAGE
.
Cuando el proceso está a punto de salir, todavía se escribirá una última cobertura en el disco a menos que se invoque v8.stopCoverage()
antes de que el proceso salga.
v8.writeHeapSnapshot([filename[,options]])
[Historial]
Versión | Cambios |
---|---|
v19.1.0 | Soporta opciones para configurar la captura del montón. |
v18.0.0 | Ahora se lanzará una excepción si el archivo no se pudo escribir. |
v18.0.0 | Hace que los códigos de error devueltos sean consistentes en todas las plataformas. |
v11.13.0 | Añadido en: v11.13.0 |
filename
<string> La ruta del archivo donde se guardará la instantánea del montón de V8. Si no se especifica, se generará un nombre de archivo con el patrón'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'
, donde{pid}
será el PID del proceso de Node.js,{thread_id}
será0
cuando se llame awriteHeapSnapshot()
desde el hilo principal de Node.js o la ID de un hilo de trabajo.options
<Object>Devuelve: <string> El nombre del archivo donde se guardó la instantánea.
Genera una instantánea del montón V8 actual y la escribe en un archivo JSON. Este archivo está destinado a ser utilizado con herramientas como Chrome DevTools. El esquema JSON no está documentado y es específico del motor V8, y puede cambiar de una versión de V8 a la siguiente.
Una instantánea de montón es específica de un único aislamiento de V8. Cuando se usan hilos de trabajo, una instantánea de montón generada desde el hilo principal no contendrá ninguna información sobre los trabajadores, y viceversa.
Crear una instantánea de montón requiere memoria aproximadamente el doble del tamaño del montón en el momento en que se crea la instantánea. Esto resulta en el riesgo de que los terminadores OOM terminen el proceso.
Generar una instantánea es una operación síncrona que bloquea el bucle de eventos durante una duración que depende del tamaño del montón.
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)
Agregado en: v18.10.0, v16.18.0
[Stable: 1 - Experimental]
Stable: 1 Estable: 1 - Experimental
limit
<integer>
La API es una no-operación si --heapsnapshot-near-heap-limit
ya está establecido desde la línea de comandos o si la API se llama más de una vez. limit
debe ser un entero positivo. Consulte --heapsnapshot-near-heap-limit
para obtener más información.
API de serialización
La API de serialización proporciona medios para serializar valores de JavaScript de una manera que sea compatible con el algoritmo de clonación estructurada HTML.
El formato es compatible con versiones anteriores (es decir, seguro para almacenar en el disco). Valores iguales de JavaScript pueden resultar en una salida serializada diferente.
v8.serialize(value)
Agregado en: v8.0.0
Utiliza un DefaultSerializer
para serializar value
en un búfer.
ERR_BUFFER_TOO_LARGE
se lanzará al intentar serializar un objeto enorme que requiere un búfer más grande que buffer.constants.MAX_LENGTH
.
v8.deserialize(buffer)
Agregado en: v8.0.0
buffer
<Buffer> | <TypedArray> | <DataView> Un búfer devuelto porserialize()
.
Utiliza un DefaultDeserializer
con opciones predeterminadas para leer un valor JS de un búfer.
Clase: v8.Serializer
Agregado en: v8.0.0
new Serializer()
Crea un nuevo objeto Serializer
.
serializer.writeHeader()
Escribe un encabezado, que incluye la versión del formato de serialización.
serializer.writeValue(value)
value
<any>
Serializa un valor de JavaScript y agrega la representación serializada al búfer interno.
Esto arroja un error si value
no se puede serializar.
serializer.releaseBuffer()
- Devuelve: <Buffer>
Devuelve el búfer interno almacenado. Este serializador no debe usarse una vez que se libera el búfer. Llamar a este método resulta en un comportamiento indefinido si una escritura anterior ha fallado.
serializer.transferArrayBuffer(id, arrayBuffer)
id
<integer> Un entero sin signo de 32 bits.arrayBuffer
<ArrayBuffer> Una instancia deArrayBuffer
.
Marca un ArrayBuffer
como que su contenido se ha transferido fuera de banda. Pase el ArrayBuffer
correspondiente en el contexto de deserialización a deserializer.transferArrayBuffer()
.
serializer.writeUint32(value)
value
<integer>
Escribe un entero sin signo de 32 bits sin procesar. Para usar dentro de un serializer._writeHostObject()
personalizado.
serializer.writeUint64(hi, lo)
Escribe un entero sin signo de 64 bits sin procesar, dividido en partes altas y bajas de 32 bits. Para usar dentro de un serializer._writeHostObject()
personalizado.
serializer.writeDouble(value)
value
<number>
Escribe un valor number
de JS. Para usar dentro de un serializer._writeHostObject()
personalizado.
serializer.writeRawBytes(buffer)
buffer
<Buffer> | <TypedArray> | <DataView>
Escribe bytes sin formato en el búfer interno del serializador. El deserializador requerirá una forma de calcular la longitud del búfer. Para usar dentro de un serializer._writeHostObject()
personalizado.
serializer._writeHostObject(object)
object
<Object>
Este método se llama para escribir algún tipo de objeto host, es decir, un objeto creado por enlaces nativos de C++. Si no es posible serializar object
, se debe lanzar una excepción adecuada.
Este método no está presente en la clase Serializer
en sí, pero puede ser proporcionado por subclases.
serializer._getDataCloneError(message)
message
<string>
Este método se llama para generar objetos de error que se lanzarán cuando un objeto no se pueda clonar.
Este método por defecto es el constructor Error
y puede ser sobrescrito en subclases.
serializer._getSharedArrayBufferId(sharedArrayBuffer)
sharedArrayBuffer
<SharedArrayBuffer>
Este método se llama cuando el serializador va a serializar un objeto SharedArrayBuffer
. Debe devolver un ID entero de 32 bits sin signo para el objeto, utilizando el mismo ID si este SharedArrayBuffer
ya ha sido serializado. Al deserializar, este ID se pasará a deserializer.transferArrayBuffer()
.
Si el objeto no se puede serializar, se debe lanzar una excepción.
Este método no está presente en la clase Serializer
en sí, pero puede ser proporcionado por subclases.
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
flag
<boolean> Predeterminado:false
Indica si se deben tratar los objetos TypedArray
y DataView
como objetos host, es decir, pasarlos a serializer._writeHostObject()
.
Clase: v8.Deserializer
Agregado en: v8.0.0
new Deserializer(buffer)
buffer
<Buffer> | <TypedArray> | <DataView> Un buffer devuelto porserializer.releaseBuffer()
.
Crea un nuevo objeto Deserializer
.
deserializer.readHeader()
Lee y valida un encabezado (incluida la versión del formato). Puede, por ejemplo, rechazar un formato de cableado no válido o no admitido. En ese caso, se lanza un Error
.
deserializer.readValue()
Deserializa un valor de JavaScript del búfer y lo devuelve.
deserializer.transferArrayBuffer(id, arrayBuffer)
id
<integer> Un entero sin signo de 32 bits.arrayBuffer
<ArrayBuffer> | <SharedArrayBuffer> Una instancia deArrayBuffer
.
Marca un ArrayBuffer
como si su contenido se hubiera transferido fuera de banda. Pasa el ArrayBuffer
correspondiente en el contexto de serialización a serializer.transferArrayBuffer()
(o devuelve el id
de serializer._getSharedArrayBufferId()
en el caso de SharedArrayBuffer
s).
deserializer.getWireFormatVersion()
- Devuelve: <integer>
Lee la versión del formato de cable subyacente. Es probable que sea más útil para el código heredado que lee versiones antiguas del formato de cable. Es posible que no se llame antes de .readHeader()
.
deserializer.readUint32()
- Devuelve: <integer>
Lee un entero sin signo de 32 bits sin formato y lo devuelve. Para usar dentro de un deserializer._readHostObject()
personalizado.
deserializer.readUint64()
- Devuelve: <integer[]>
Lee un entero sin signo de 64 bits sin formato y lo devuelve como un array [hi, lo]
con dos entradas de entero sin signo de 32 bits. Para usar dentro de un deserializer._readHostObject()
personalizado.
deserializer.readDouble()
- Devuelve: <number>
Lee un valor number
de JS. Para usar dentro de un deserializer._readHostObject()
personalizado.
deserializer.readRawBytes(length)
Lee bytes sin formato del búfer interno del deserializador. El parámetro length
debe corresponder a la longitud del búfer que se pasó a serializer.writeRawBytes()
. Para usar dentro de un deserializer._readHostObject()
personalizado.
deserializer._readHostObject()
Este método se llama para leer algún tipo de objeto host, es decir, un objeto que es creado por enlaces nativos de C++. Si no es posible deserializar los datos, se debe lanzar una excepción adecuada.
Este método no está presente en la propia clase Deserializer
, pero puede ser proporcionado por subclases.
Clase: v8.DefaultSerializer
Agregado en: v8.0.0
Una subclase de Serializer
que serializa objetos TypedArray
(en particular Buffer
) y DataView
como objetos host, y solo almacena la parte de sus ArrayBuffer
subyacentes a las que se refieren.
Clase: v8.DefaultDeserializer
Agregado en: v8.0.0
Una subclase de Deserializer
correspondiente al formato escrito por DefaultSerializer
.
Enlaces de Promise
La interfaz promiseHooks
se puede utilizar para rastrear los eventos del ciclo de vida de las promesas. Para rastrear toda la actividad asíncrona, consulte async_hooks
que internamente utiliza este módulo para producir eventos del ciclo de vida de la promesa además de los eventos para otros recursos asíncronos. Para la gestión del contexto de la solicitud, consulte AsyncLocalStorage
.
import { promiseHooks } from 'node:v8';
// Hay cuatro eventos del ciclo de vida producidos por las promesas:
// El evento `init` representa la creación de una promesa. Esto podría ser una
// creación directa como con `new Promise(...)` o una continuación como
// como `then()` o `catch()`. También ocurre cada vez que se llama a una función asíncrona o
// hace un `await`. Si se crea una promesa de continuación, el
// `parent` será la promesa de la que es una continuación.
function init(promise, parent) {
console.log('se creó una promesa', { promise, parent });
}
// El evento `settled` ocurre cuando una promesa recibe una resolución o
// valor de rechazo. Esto puede suceder sincrónicamente, como cuando se usa
// `Promise.resolve()` en una entrada que no es promesa.
function settled(promise) {
console.log('una promesa se resolvió o rechazó', { promise });
}
// El evento `before` se ejecuta inmediatamente antes de que se ejecute un controlador `then()` o `catch()`
// se ejecuta o un `await` reanuda la ejecución.
function before(promise) {
console.log('una promesa está a punto de llamar a un controlador then', { promise });
}
// El evento `after` se ejecuta inmediatamente después de que se ejecuta un controlador `then()` o cuando
// un `await` comienza después de reanudar desde otro.
function after(promise) {
console.log('una promesa terminó de llamar a un controlador then', { promise });
}
// Los enlaces del ciclo de vida se pueden iniciar y detener individualmente
const stopWatchingInits = promiseHooks.onInit(init);
const stopWatchingSettleds = promiseHooks.onSettled(settled);
const stopWatchingBefores = promiseHooks.onBefore(before);
const stopWatchingAfters = promiseHooks.onAfter(after);
// O pueden iniciarse y detenerse en grupos
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
});
// Para detener un enlace, llame a la función devuelta en su creación.
stopWatchingInits();
stopWatchingSettleds();
stopWatchingBefores();
stopWatchingAfters();
stopHookSet();
promiseHooks.onInit(init)
Agregado en: v17.1.0, v16.14.0
init
<Function> Lainit
callback a llamar cuando se crea una promesa.- Regresa: <Function> Llama para detener el hook.
El hook init
debe ser una función simple. Proporcionar una función async lanzará un error ya que produciría un bucle de microtareas infinito.
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)
Agregado en: v17.1.0, v16.14.0
settled
<Function> Lasettled
callback a llamar cuando una promesa es resuelta o rechazada.- Regresa: <Function> Llama para detener el hook.
El hook settled
debe ser una función simple. Proporcionar una función async lanzará un error ya que produciría un bucle de microtareas infinito.
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onSettled((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onSettled((promise) => {});
promiseHooks.onBefore(before)
Agregado en: v17.1.0, v16.14.0
before
<Function> Labefore
callback a llamar antes de que una continuación de promesa se ejecute.- Regresa: <Function> Llama para detener el hook.
El hook before
debe ser una función simple. Proporcionar una función async lanzará un error ya que produciría un bucle de microtareas infinito.
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onBefore((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onBefore((promise) => {});
promiseHooks.onAfter(after)
Añadido en: v17.1.0, v16.14.0
after
<Function> Laafter
callback a la que se llama después de que se ejecute una continuación de promesa.- Devuelve: <Function> Llamar para detener el hook.
El hook after
debe ser una función simple. Proporcionar una función asíncrona lanzará un error, ya que produciría un bucle de microtareas infinito.
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onAfter((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onAfter((promise) => {});
promiseHooks.createHook(callbacks)
Añadido en: v17.1.0, v16.14.0
callbacks
<Object> Los Hook Callbacks para registrarinit
<Function> Lainit
callback.before
<Function> Labefore
callback.after
<Function> Laafter
callback.settled
<Function> Lasettled
callback.
Devuelve: <Function> Se utiliza para deshabilitar los hooks
Las callbacks de hook deben ser funciones simples. Proporcionar funciones asíncronas lanzará un error, ya que produciría un bucle de microtareas infinito.
Registra funciones para ser llamadas para diferentes eventos del ciclo de vida de cada promesa.
Las callbacks init()
/before()
/after()
/settled()
se llaman para los respectivos eventos durante el ciclo de vida de una promesa.
Todas las callbacks son opcionales. Por ejemplo, si solo es necesario rastrear la creación de promesas, entonces solo necesita pasarse la callback init
. Los detalles de todas las funciones que se pueden pasar a callbacks
están en la sección 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) {},
});
Retrollamadas de Hook
Los eventos clave en el ciclo de vida de una promesa se han categorizado en cuatro áreas: creación de una promesa, antes/después de que se llame a un controlador de continuación o alrededor de un await, y cuando la promesa se resuelve o rechaza.
Si bien estos hooks son similares a los de async_hooks
, carecen de un hook destroy
. Otros tipos de recursos asíncronos suelen representar sockets o descriptores de archivo que tienen un estado "cerrado" distinto para expresar el evento del ciclo de vida destroy
, mientras que las promesas siguen siendo utilizables mientras el código aún pueda alcanzarlas. El seguimiento de la recolección de basura se utiliza para hacer que las promesas encajen en el modelo de eventos async_hooks
, sin embargo, este seguimiento es muy costoso y es posible que nunca se recolecten como basura.
Debido a que las promesas son recursos asíncronos cuyo ciclo de vida se rastrea a través del mecanismo de hooks de promesa, las retrollamadas init()
, before()
, after()
y settled()
no deben ser funciones async, ya que crean más promesas que producirían un bucle infinito.
Si bien esta API se utiliza para alimentar eventos de promesa en async_hooks
, el orden entre los dos no está definido. Ambas API son multiinquilino y, por lo tanto, podrían producir eventos en cualquier orden entre sí.
init(promise, parent)
promise
<Promise> La promesa que se está creando.parent
<Promise> La promesa continuada desde, si corresponde.
Se llama cuando se construye una promesa. Esto no significa que se producirán eventos before
/after
correspondientes, solo que existe la posibilidad. Esto sucederá si se crea una promesa sin obtener nunca una continuación.
before(promise)
promise
<Promise>
Se llama antes de que se ejecute una continuación de promesa. Esto puede ser en forma de controladores then()
, catch()
o finally()
o una reanudación de await
.
La retrollamada before
se llamará de 0 a N veces. La retrollamada before
normalmente se llamará 0 veces si nunca se realizó ninguna continuación para la promesa. La retrollamada before
se puede llamar muchas veces en el caso de que se hayan realizado muchas continuaciones desde la misma promesa.
after(promise)
promise
<Promise>
Se llama inmediatamente después de que se ejecuta una continuación de promesa. Esto puede ser después de un controlador then()
, catch()
o finally()
o antes de un await
después de otro await
.
settled(promise)
promise
<Promise>
Se llama cuando la promesa recibe un valor de resolución o rechazo. Esto puede ocurrir sincrónicamente en el caso de Promise.resolve()
o Promise.reject()
.
API de Instantánea de Inicio
Agregado en: v18.6.0, v16.17.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1 - Experimental
La interfaz v8.startupSnapshot
se puede utilizar para agregar hooks de serialización y deserialización para instantáneas de inicio personalizadas.
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# Esto inicia un proceso con la instantánea {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob
En el ejemplo anterior, entry.js
puede usar métodos de la interfaz v8.startupSnapshot
para especificar cómo guardar información para objetos personalizados en la instantánea durante la serialización y cómo la información se puede utilizar para sincronizar estos objetos durante la deserialización de la instantánea. Por ejemplo, si entry.js
contiene el siguiente script:
'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);
El binario resultante imprimirá los datos deserializados de la instantánea durante el inicio, utilizando los process.env
y process.argv
actualizados del proceso iniciado:
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Prints content of book1.es_ES.txt deserialized from the snapshot. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}
Actualmente, la aplicación deserializada de una instantánea del espacio de usuario no se puede volver a tomar una instantánea, por lo que estas API solo están disponibles para las aplicaciones que no se deserializan de una instantánea del espacio de usuario.
v8.startupSnapshot.addSerializeCallback(callback[, data])
Agregado en: v18.6.0, v16.17.0
callback
<Function> Callback que se invocará antes de la serialización.data
<any> Datos opcionales que se pasarán alcallback
cuando se llame.
Agregue un callback que se llamará cuando la instancia de Node.js esté a punto de serializarse en una instantánea y salir. Esto se puede usar para liberar recursos que no deberían o no pueden serializarse o para convertir los datos del usuario en una forma más adecuada para la serialización.
Los callbacks se ejecutan en el orden en que se agregan.
v8.startupSnapshot.addDeserializeCallback(callback[, data])
Agregado en: v18.6.0, v16.17.0
callback
<Function> Callback que se invocará después de deserializar la instantánea.data
<any> Datos opcionales que se pasarán alcallback
cuando se llame.
Agregue un callback que se llamará cuando la instancia de Node.js se deserialice desde una instantánea. El callback
y los data
(si se proporcionan) se serializarán en la instantánea, se pueden usar para reinicializar el estado de la aplicación o para volver a adquirir los recursos que la aplicación necesita cuando la aplicación se reinicia desde la instantánea.
Los callbacks se ejecutan en el orden en que se agregan.
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
Agregado en: v18.6.0, v16.17.0
callback
<Function> Callback que se invocará como el punto de entrada después de que se deserialice la instantánea.data
<any> Datos opcionales que se pasarán alcallback
cuando se llame.
Esto establece el punto de entrada de la aplicación Node.js cuando se deserializa desde una instantánea. Esto se puede llamar solo una vez en el script de construcción de instantáneas. Si se llama, la aplicación deserializada ya no necesita un script de punto de entrada adicional para iniciarse y simplemente invocará el callback junto con los datos deserializados (si se proporcionan), de lo contrario, aún debe proporcionarse un script de punto de entrada a la aplicación deserializada.
v8.startupSnapshot.isBuildingSnapshot()
Agregada en: v18.6.0, v16.17.0
- Devuelve: <boolean>
Devuelve true si la instancia de Node.js se está ejecutando para construir una instantánea.
Clase: v8.GCProfiler
Agregada en: v19.6.0, v18.15.0
Esta API recopila datos de GC en el hilo actual.
new v8.GCProfiler()
Agregada en: v19.6.0, v18.15.0
Crea una nueva instancia de la clase v8.GCProfiler
.
profiler.start()
Agregada en: v19.6.0, v18.15.0
Comienza a recopilar datos de GC.
profiler.stop()
Agregada en: v19.6.0, v18.15.0
Deja de recopilar datos de GC y devuelve un objeto. El contenido del objeto es el siguiente.
{
"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
}
Aquí hay un ejemplo.
const { GCProfiler } = require('node:v8');
const profiler = new GCProfiler();
profiler.start();
setTimeout(() => {
console.log(profiler.stop());
}, 1000);