Skip to content

V8

Código fuente: lib/v8.js

El módulo node:v8 expone las API que son específicas de la versión de V8 integrada en el binario de Node.js. Se puede acceder a él usando:

js
const v8 = require('node:v8')

v8.cachedDataVersionTag()

Añadido en: v8.0.0

Devuelve un entero que representa una etiqueta de versión derivada de la versión de V8, las banderas de línea de comandos y las características de CPU detectadas. Esto es útil para determinar si un búfer cachedData de vm.Script es compatible con esta instancia de V8.

js
console.log(v8.cachedDataVersionTag()) // 3947234607
// El valor devuelto por v8.cachedDataVersionTag() se deriva de la versión de V8,
// las banderas de la línea de comandos y las características de la CPU detectadas.
// Comprueba que el valor se actualice cuando se cambian las banderas.
v8.setFlagsFromString('--allow_natives_syntax')
console.log(v8.cachedDataVersionTag()) // 183726201

v8.getHeapCodeStatistics()

Agregado en: v12.8.0

Obtiene estadísticas sobre el código y sus metadatos en el heap, consulta la API V8 GetHeapCodeAndMetadataStatistics. Devuelve un objeto con las siguientes propiedades:

js
{
  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ónCambios
v19.1.0Soporte para opciones para configurar la instantánea del montón.
v11.13.0Añadido en: v11.13.0
  • options <Object>

    • exposeInternals <boolean> Si es true, expone los internos en la instantánea del montón. Predeterminado: false.
    • exposeNumericValues <boolean> Si es true, expone los valores numéricos en campos artificiales. Predeterminado: false.
  • Devuelve: <stream.Readable> Un Readable que contiene la instantánea del montón V8.

Genera una instantánea del montón V8 actual y devuelve un Stream Readable que puede usarse para leer la representación serializada en JSON. Este formato de stream JSON está pensado para usarse 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.

La creación de una instantánea del montón requiere una memoria aproximadamente el doble del tamaño del montón en el momento en que se crea la instantánea. Esto genera el riesgo de que los eliminadores OOM terminen el proceso.

La generación de una instantánea es una operación síncrona que bloquea el bucle de eventos durante un período que depende del tamaño del montón.

js
// Imprimir la instantánea del montón en la consola
const v8 = require('node:v8')
const stream = v8.getHeapSnapshot()
stream.pipe(process.stdout)

v8.getHeapSpaceStatistics()

[Historial]

VersiónCambios
v7.5.0Soporte para valores que exceden el rango de enteros sin signo de 32 bits.
v6.0.0Añadido en: v6.0.0

Devuelve estadísticas sobre los espacios de memoria heap de V8, es decir, los segmentos que componen el heap de V8. No se puede garantizar ni el orden de los espacios de memoria heap ni la disponibilidad de un espacio de memoria heap, ya que las estadísticas se proporcionan a través de la función GetHeapSpaceStatistics de V8 y pueden cambiar de una versión de V8 a otra.

El valor devuelto es un array de objetos que contiene las siguientes propiedades:

json
[
  {
    "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ónCambios
v7.5.0Soporte para valores que exceden el rango de enteros sin signo de 32 bits.
v7.2.0Se agregaron malloced_memory, peak_malloced_memory y does_zap_garbage.
v1.0.0Agregado en: v1.0.0

Devuelve un objeto con las siguientes propiedades:

total_heap_size El valor de total_heap_size es el número de bytes que V8 ha asignado para el montón. Esto puede crecer si used_heap necesita más memoria.

total_heap_size_executable El valor de total_heap_size_executable es la parte del montón que puede contener código ejecutable, en bytes. Esto incluye la memoria utilizada por el código compilado por 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 montón de V8, en bytes. Esta es la cantidad de memoria que se confirma (o está en uso) en lugar de reservarse.

total_available_size El valor de total_available_size es el número de bytes de memoria disponible para el montón de V8. Este valor representa cuánta más memoria puede usar V8 antes de exceder el límite del montón.

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 montón 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 de 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 desprendieron y aún no se han recogido 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 manejadores globales de V8.

used_global_handles_size El valor de used_global_handles_size es el tamaño de memoria utilizado de los manejadores globales de V8.

external_memory El valor de external_memory es el tamaño de memoria de los búferes de matriz y las cadenas externas.

js
{
  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])

Añadido en: v22.0.0, v20.13.0

[Estable: 1 - Experimental]

Estable: 1 Estabilidad: 1.1 - Desarrollo activo

  • ctor <Function> El constructor que puede ser usado para buscar en la cadena de prototipos con el fin de filtrar los objetos objetivo en el heap.

  • options <undefined> | <Object>

    • format <string> Si es 'count', se retorna el conteo de objetos encontrados. Si es 'summary', se retorna un array con cadenas de resumen de los objetos encontrados.
  • Retorna: {number|Array

Esto es similar a la API de consola queryObjects() proporcionada por la consola de Chromium DevTools. Puede ser usada para buscar objetos que tienen el constructor coincidente en su cadena de prototipos en el heap después de una recolección de basura completa, lo que puede ser útil para 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 retorna referencias sin procesar a los objetos encontrados. Por defecto, retorna el conteo de objetos encontrados. Si options.format es 'summary', retorna un array conteniendo representaciones de cadena breves para cada objeto. La visibilidad proporcionada en esta API es similar a la que proporciona la instantánea del heap, mientras que los usuarios pueden ahorrar el costo de serialización y 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.

js
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 que, cuando hay clases hijas que heredan de un constructor,
// el constructor también aparece en la cadena de prototipos del prototipo
// de las clases hijas, por lo que el prototipo de las clases hijas también se
// incluiría en el resultado.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))
js
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 que, cuando hay clases hijas que heredan de un constructor,
// el constructor también aparece en la cadena de prototipos del prototipo
// de las clases hijas, por lo que el prototipo de las clases hijas también se
// incluiría en el resultado.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

v8.setFlagsFromString(flags)

Agregado en: v1.0.0

El método v8.setFlagsFromString() se puede usar para establecer programáticamente las banderas de línea de comandos de V8. Este método debe usarse con cuidado. Cambiar la configuración después de que la VM se haya iniciado puede resultar en un comportamiento impredecible, incluyendo bloqueos y pérdida de datos; o simplemente puede no hacer nada.

Las opciones de V8 disponibles para una versión de Node.js se pueden determinar ejecutando node --v8-options.

Uso:

js
// 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()

Agregado en: v15.1.0, v14.18.0, v12.22.0

El método v8.stopCoverage() permite al usuario detener la colección de cobertura iniciada por NODE_V8_COVERAGE, para que V8 pueda liberar los registros de conteo de ejecución y optimizar el código. Esto se puede usar junto con v8.takeCoverage() si el usuario quiere recolectar la cobertura bajo demanda.

v8.takeCoverage()

Agregado 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 puede ser invocado varias veces durante la vida del proceso. Cada vez, el contador de ejecución se restablecerá y se escribirá un nuevo informe de cobertura en el directorio especificado por NODE_V8_COVERAGE.

Cuando el proceso está a punto de salir, 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ónCambios
v19.1.0Soporte para opciones para configurar la instantánea de montón.
v18.0.0Ahora se lanzará una excepción si no se pudo escribir el archivo.
v18.0.0Hacer que los códigos de error devueltos sean consistentes en todas las plataformas.
v11.13.0Agregado en: v11.13.0
  • filename <string> La ruta de archivo donde se guardará la instantánea de 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 a writeHeapSnapshot() desde el hilo principal de Node.js o el ID de un hilo de trabajo.

  • options <Object>

    • exposeInternals <boolean> Si es verdadero, expone internos en la instantánea del montón. Predeterminado: false.
    • exposeNumericValues <boolean> Si es verdadero, expone valores numéricos en campos artificiales. Predeterminado: false.
  • Devuelve: <string> El nombre de archivo donde se guardó la instantánea.

Genera una instantánea del montón de 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 aislado 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 una memoria aproximadamente dos veces el 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.

js
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(`volcado de montón del trabajador: ${filename}`)
    // Ahora obtener un volcado de montón para el hilo principal.
    console.log(`volcado de montón del hilo principal: ${writeHeapSnapshot()}`)
  })

  // Decir al trabajador que cree un volcado de montón.
  worker.postMessage('heapdump')
} else {
  parentPort.once('message', message => {
    if (message === 'heapdump') {
      // Generar un volcado de montón para el trabajador
      // y devolver el nombre de archivo al padre.
      parentPort.postMessage(writeHeapSnapshot())
    }
  })
}

v8.setHeapSnapshotNearHeapLimit(limit)

Añadido en: v18.10.0, v16.18.0

[Estable: 1 - Experimental]

Estable: 1 Estabilidad: 1 - Experimental

La API no realiza ninguna operación si --heapsnapshot-near-heap-limit ya se ha establecido desde la línea de comandos o si se llama a la API más de una vez. limit debe ser un entero positivo. Consulta --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 guardar en disco). Los valores de JavaScript iguales pueden dar como resultado una salida serializada diferente.

v8.serialize(value)

Agregado en: v8.0.0

Utiliza un DefaultSerializer para serializar value en un búfer.

Se lanzará ERR_BUFFER_TOO_LARGE 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

Utiliza un DefaultDeserializer con opciones predeterminadas para leer un valor JS desde 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)

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 el búfer interno almacenado. Este serializador no debe utilizarse 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)

Marca un ArrayBuffer como si su contenido se hubiera transferido fuera de banda. Pase el ArrayBuffer correspondiente en el contexto de deserialización a deserializer.transferArrayBuffer().

serializer.writeUint32(value)

Escribe un entero sin signo de 32 bits sin formato. Para uso dentro de un serializer._writeHostObject() personalizado.

serializer.writeUint64(hi, lo)

Escribe un entero sin signo de 64 bits sin formato, dividido en partes de 32 bits alta y baja. Para uso dentro de un serializer._writeHostObject() personalizado.

serializer.writeDouble(value)

Escribe un valor number de JS. Para uso dentro de un serializer._writeHostObject() personalizado.

serializer.writeRawBytes(buffer)

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)

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 generar una excepción adecuada.

Este método no está presente en la propia clase Serializer, pero puede ser proporcionado por subclases.

serializer._getDataCloneError(message)

Este método se llama para generar objetos de error que se generarán cuando un objeto no se pueda clonar.

Este método tiene como valor predeterminado el constructor Error y se puede sobrescribir en las subclases.

serializer._getSharedArrayBufferId(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, usando el mismo ID si este SharedArrayBuffer ya ha sido serializado. Al deserializar, este ID se pasará a deserializer.transferArrayBuffer().

Si el objeto no puede ser serializado, se debe lanzar una excepción.

Este método no está presente en la clase Serializer en sí, pero puede ser proporcionado por las subclases.

serializer._setTreatArrayBufferViewsAsHostObjects(flag)

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)

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 cable no válido o no compatible. En ese caso, se genera un Error.

deserializer.readValue()

Deserializa un valor de JavaScript del búfer y lo devuelve.

deserializer.transferArrayBuffer(id, arrayBuffer)

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 SharedArrayBuffers).

deserializer.getWireFormatVersion()

Lee la versión del formato de cable subyacente. Es probable que sea útil principalmente para el código heredado que lee versiones antiguas del formato de cable. Puede que no se llame antes de .readHeader().

deserializer.readUint32()

Lee un entero sin signo sin procesar de 32 bits y lo devuelve. Para usar dentro de un deserializer._readHostObject() personalizado.

deserializer.readUint64()

Lee un entero sin signo sin procesar de 64 bits y lo devuelve como una matriz [hi, lo] con dos entradas de enteros sin signo de 32 bits. Para usar dentro de un deserializer._readHostObject() personalizado.

deserializer.readDouble()

Lee un valor number de JS. Para usar dentro de un deserializer._readHostObject() personalizado.

deserializer.readRawBytes(length)

Lee bytes sin procesar 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()

Se llama a este método para leer algún tipo de objeto host, es decir, un objeto que se crea mediante enlaces nativos de C++. Si no es posible deserializar los datos, se debe generar una excepción adecuada.

Este método no está presente en la clase Deserializer en sí, pero puede ser proporcionado por las 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

Añadido en: v8.0.0

Una subclase de Deserializer correspondiente al formato escrito por DefaultSerializer.

Ganchos de Promesas

La interfaz promiseHooks se puede usar para rastrear eventos del ciclo de vida de las promesas. Para rastrear toda la actividad asíncrona, vea async_hooks que internamente usa este módulo para producir eventos del ciclo de vida de las promesas además de eventos para otros recursos asíncronos. Para la gestión del contexto de la solicitud, vea AsyncLocalStorage.

js
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
// `then()` o `catch()`. También sucede cuando se llama a una función async o
// se 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` sucede cuando una promesa recibe una resolución o
// un valor de rechazo. Esto puede suceder de forma síncrona, como cuando se usa
// `Promise.resolve()` en una entrada que no es una 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()`
// o se reanude la ejecución de un `await`.
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 reanudarse desde otro.
function after(promise) {
  console.log('una promesa terminó de llamar a un controlador then', { promise })
}

// Los ganchos 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 se pueden iniciar y detener en grupos
const stopHookSet = promiseHooks.createHook({
  init,
  settled,
  before,
  after,
})

// Para detener un gancho, 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> La función de retrollamada init que se debe llamar cuando se crea una promesa.
  • Devuelve: <Function> Llamar para detener el gancho.

El gancho init debe ser una función simple. Proporcionar una función asíncrona lanzará un error, ya que produciría un bucle de microtareas infinito.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onInit((promise, parent) => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onInit((promise, parent) => {})

promiseHooks.onSettled(settled)

Agregado en: v17.1.0, v16.14.0

  • settled <Function> La función de retrollamada settled que se debe llamar cuando una promesa se resuelve o se rechaza.
  • Devuelve: <Function> Llamar para detener el gancho.

El gancho settled debe ser una función simple. Proporcionar una función asíncrona lanzará un error, ya que produciría un bucle de microtareas infinito.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onSettled(promise => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onSettled(promise => {})

promiseHooks.onBefore(before)

Agregado en: v17.1.0, v16.14.0

  • before <Función> La retrollamada before para llamar antes de que se ejecute una continuación de la promesa.
  • Devuelve: <Función> Llamar para detener el gancho.

El gancho before debe ser una función simple. Proporcionar una función async arrojará un error ya que produciría un bucle infinito de microtareas.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onBefore(promise => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onBefore(promise => {})

promiseHooks.onAfter(after)

Agregado en: v17.1.0, v16.14.0

  • after <Función> La retrollamada after para llamar después de que se ejecute una continuación de la promesa.
  • Devuelve: <Función> Llamar para detener el gancho.

El gancho after debe ser una función simple. Proporcionar una función async arrojará un error ya que produciría un bucle infinito de microtareas.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onAfter(promise => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onAfter(promise => {})

promiseHooks.createHook(callbacks)

Añadido en: v17.1.0, v16.14.0

Las funciones de retorno del hook deben ser funciones simples. Proporcionar funciones asíncronas provocará un error, ya que produciría un bucle de microtareas infinito.

Registra las funciones que se llamarán para diferentes eventos del ciclo de vida de cada promesa.

Las funciones de retorno init()/before()/after()/settled() se llaman para los eventos respectivos durante el ciclo de vida de una promesa.

Todas las funciones de retorno son opcionales. Por ejemplo, si solo es necesario realizar un seguimiento de la creación de promesas, solo es necesario pasar la función de retorno init. Los detalles de todas las funciones que se pueden pasar a callbacks se encuentran en la sección Funciones de retorno de Hook.

js
import { promiseHooks } from 'node:v8'

const stopAll = promiseHooks.createHook({
  init(promise, parent) {},
})
js
const { promiseHooks } = require('node:v8')

const stopAll = promiseHooks.createHook({
  init(promise, parent) {},
})

Hook callbacks

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 se 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 archivos que tienen un estado "cerrado" distinto para expresar el evento del ciclo de vida destroy, mientras que las promesas siguen siendo utilizables siempre que el código aún pueda alcanzarlas. El seguimiento de la recolección de basura se utiliza para que las promesas encajen en el modelo de eventos de async_hooks, sin embargo, este seguimiento es muy costoso y es posible que nunca se recolecten como basura.

Dado que las promesas son recursos asíncronos cuyo ciclo de vida se rastrea a través del mecanismo de hooks de promesas, las devoluciones de llamada init(), before(), after() y settled() no deben ser funciones asíncronas, ya que crean más promesas que producirían un bucle infinito.

Si bien esta API se utiliza para introducir eventos de promesas en async_hooks, el orden entre los dos no está definido. Ambas API son multi-inquilino y, por lo tanto, podrían producir eventos en cualquier orden relativo entre sí.

init(promise, parent)

  • promise <Promise> La promesa que se está creando.
  • parent <Promise> La promesa de la que se continúa, si corresponde.

Se llama cuando se construye una promesa. Esto no significa que ocurrirán los eventos before/after correspondientes, solo que existe la posibilidad. Esto sucederá si se crea una promesa sin obtener nunca una continuación.

before(promise)

Se llama antes de que se ejecute una continuación de promesa. Esto puede ser en la forma de controladores then(), catch() o finally() o un await reanudándose.

La devolución de llamada before se llamará de 0 a N veces. La devolución de llamada before se llamará normalmente 0 veces si nunca se realizó ninguna continuación para la promesa. La devolución de llamada before puede llamarse muchas veces en el caso de que se hayan realizado muchas continuaciones a partir de la misma promesa.

after(promise)

Se llama inmediatamente después de que se ejecuta una continuación de promesa. Esto puede ser después de un manejador then(), catch() o finally() o antes de un await después de otro await.

settled(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

Añadido en: v18.6.0, v16.17.0

[Estable: 1 - Experimental]

Estable: 1 Estabilidad: 1 - Experimental

La interfaz v8.startupSnapshot se puede usar para añadir hooks de serialización y deserialización para instantáneas de inicio personalizadas.

bash
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# Esto lanza un proceso con la instantánea {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob

En el ejemplo de arriba, 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 se puede usar la información para sincronizar estos objetos durante la deserialización de la instantánea. Por ejemplo, si entry.js contiene el siguiente script:

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()

  // Leyendo una serie de archivos de un directorio y guardándolos en 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 aquí es donde se coloca el script de la instantánea
// durante el tiempo de creación de la instantánea.
const shelf = new BookShelf(__dirname, ['book1.en_US.txt', 'book1.es_ES.txt', 'book2.zh_CN.txt'])

assert(v8.startupSnapshot.isBuildingSnapshot())
// En la serialización de la instantánea, comprime los libros para reducir el tamaño.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf)
// En la deserialización de la instantánea, descomprime los libros.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf)
v8.startupSnapshot.setDeserializeMainFunction(shelf => {
  // process.env y process.argv se actualizan durante la instantánea
  // deserialización.
  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, usando process.env y process.argv actualizados del proceso lanzado:

bash
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Imprime el contenido de book1.es_ES.txt deserializado de la instantánea. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}

Actualmente, la aplicación deserializada de una instantánea de usuario no se puede volver a instantanear, por lo que estas API solo están disponibles para aplicaciones que no se deserializan de una instantánea 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 a la callback cuando se llame.

Agrega una callback que se llamará cuando la instancia de Node.js esté a punto de ser serializada en una instantánea y salir. Esto se puede usar para liberar recursos que no deben o no pueden ser serializados o para convertir los datos del usuario en una forma más adecuada para la serialización.

Las 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 que se deserialice la instantánea.
  • data <any> Datos opcionales que se pasarán a la callback cuando se llame.

Agrega una callback que se llamará cuando la instancia de Node.js se deserialice de una instantánea. La 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.

Las 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 punto de entrada después de que se deserialice la instantánea.
  • data <any> Datos opcionales que se pasarán a la callback cuando se llame.

Esto establece el punto de entrada de la aplicación Node.js cuando se deserializa desde una instantánea. Esto solo se puede llamar una vez en el script de construcción de la instantánea. Si se llama, la aplicación deserializada ya no necesita un script de punto de entrada adicional para iniciarse y simplemente invocará la callback junto con los datos deserializados (si se proporcionan), de lo contrario, todavía se debe proporcionar un script de punto de entrada a la aplicación deserializada.

v8.startupSnapshot.isBuildingSnapshot()

Agregado en: v18.6.0, v16.17.0

Devuelve verdadero si la instancia de Node.js se ejecuta para construir una instantánea.

Clase: v8.GCProfiler

Agregado en: v19.6.0, v18.15.0

Esta API recopila datos de GC en el hilo actual.

new v8.GCProfiler()

Agregado en: v19.6.0, v18.15.0

Crea una nueva instancia de la clase v8.GCProfiler.

profiler.start()

Agregado en: v19.6.0, v18.15.0

Comienza a recopilar datos de GC.

profiler.stop()

Agregado en: v19.6.0, v18.15.0

Detiene la recopilación de datos de GC y devuelve un objeto. El contenido del objeto es el siguiente.

json
{
  "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.

js
const { GCProfiler } = require('node:v8')
const profiler = new GCProfiler()
profiler.start()
setTimeout(() => {
  console.log(profiler.stop())
}, 1000)