V8
Código-fonte: lib/v8.js
O módulo node:v8
expõe APIs específicas para a versão do V8 integrado ao binário do Node.js. Ele pode ser acessado usando:
const v8 = require('node:v8')
v8.cachedDataVersionTag()
Adicionado em: v8.0.0
- Retorna: <inteiro>
Retorna um inteiro representando uma tag de versão derivada da versão do V8, flags de linha de comando e recursos de CPU detectados. Isso é útil para determinar se um buffer cachedData
de vm.Script
é compatível com esta instância do V8.
console.log(v8.cachedDataVersionTag()) // 3947234607
// O valor retornado por v8.cachedDataVersionTag() é derivado da versão do V8,
// flags de linha de comando e recursos de CPU detectados. Teste se o valor
// de fato se atualiza quando as flags são alteradas.
v8.setFlagsFromString('--allow_natives_syntax')
console.log(v8.cachedDataVersionTag()) // 183726201
v8.getHeapCodeStatistics()
Adicionado em: v12.8.0
- Retorna: <Objeto>
Obtém estatísticas sobre o código e seus metadados no heap, consulte a API V8 GetHeapCodeAndMetadataStatistics
. Retorna um objeto com as seguintes propriedades:
code_and_metadata_size
<número>bytecode_and_metadata_size
<número>external_script_source_size
<número>cpu_profiler_metadata_size
<número>
{
code_and_metadata_size: 212208,
bytecode_and_metadata_size: 161368,
external_script_source_size: 1410794,
cpu_profiler_metadata_size: 0,
}
v8.getHeapSnapshot([options])
[Histórico]
Versão | Alterações |
---|---|
v19.1.0 | Suporte a opções para configurar o snapshot do heap. |
v11.13.0 | Adicionado em: v11.13.0 |
options
<Object>Retorna: <stream.Readable> Um
Readable
contendo o snapshot do heap V8.
Gera um snapshot do heap V8 atual e retorna um fluxo Readable Stream
que pode ser usado para ler a representação serializada JSON. Este formato de fluxo JSON destina-se a ser usado com ferramentas como o Chrome DevTools. O esquema JSON não é documentado e é específico para o mecanismo V8. Portanto, o esquema pode mudar de uma versão do V8 para a próxima.
Criar um snapshot do heap requer memória aproximadamente duas vezes o tamanho do heap no momento em que o snapshot é criado. Isso resulta no risco de terminadores OOM interromperem o processo.
Gerar um snapshot é uma operação síncrona que bloqueia o loop de eventos por uma duração que depende do tamanho do heap.
// Imprime o snapshot do heap no console
const v8 = require('node:v8')
const stream = v8.getHeapSnapshot()
stream.pipe(process.stdout)
v8.getHeapSpaceStatistics()
[Histórico]
Versão | Alterações |
---|---|
v7.5.0 | Suporte a valores que excedem a faixa de inteiros sem sinal de 32 bits. |
v6.0.0 | Adicionado em: v6.0.0 |
- Retorna: <Object[]>
Retorna estatísticas sobre os espaços de heap V8, ou seja, os segmentos que compõem o heap V8. Nem a ordem dos espaços de heap, nem a disponibilidade de um espaço de heap podem ser garantidas, pois as estatísticas são fornecidas por meio da função V8 GetHeapSpaceStatistics
e podem mudar de uma versão do V8 para a próxima.
O valor retornado é um array de objetos contendo as seguintes propriedades:
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()
[Histórico]
Versão | Alterações |
---|---|
v7.5.0 | Suporte a valores que excedem a faixa de inteiros sem sinal de 32 bits. |
v7.2.0 | Adicionado malloced_memory , peak_malloced_memory , e does_zap_garbage . |
v1.0.0 | Adicionado em: v1.0.0 |
- Retorna: <Objeto>
Retorna um objeto com as seguintes propriedades:
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
O valor de total_heap_size
é o número de bytes que o V8 alocou para o heap. Isso pode crescer se used_heap
precisar de mais memória.
total_heap_size_executable
O valor de total_heap_size_executable
é a parte do heap que pode conter código executável, em bytes. Isso inclui memória usada por código compilado por JIT e qualquer memória que deve ser mantida executável.
total_physical_size
O valor de total_physical_size
é a memória física real usada pelo heap do V8, em bytes. Esta é a quantidade de memória que está comprometida (ou em uso) em vez de reservada.
total_available_size
O valor de total_available_size
é o número de bytes de memória disponíveis para o heap do V8. Este valor representa quanta memória adicional o V8 pode usar antes de exceder o limite do heap.
used_heap_size
O valor de used_heap_size
é o número de bytes atualmente sendo usados pelos objetos JavaScript do V8. Esta é a memória real em uso e não inclui a memória que foi alocada, mas ainda não usada.
heap_size_limit
O valor de heap_size_limit
é o tamanho máximo do heap do V8, em bytes (o limite padrão, determinado pelos recursos do sistema, ou o valor passado para a opção --max_old_space_size
).
malloced_memory
O valor de malloced_memory
é o número de bytes alocados através de malloc
pelo V8.
peak_malloced_memory
O valor de peak_malloced_memory
é o número máximo de bytes alocados através de malloc
pelo V8 durante a vida útil do processo.
does_zap_garbage
é um booleano 0/1, que significa se a opção --zap_code_space
está habilitada ou não. Isso faz com que o V8 sobrescreva o lixo do heap com um padrão de bits. A pegada RSS (tamanho do conjunto residente) fica maior porque ela continuamente toca todas as páginas do heap e isso torna menos provável que elas sejam trocadas pelo sistema operacional.
number_of_native_contexts
O valor de native_context
é o número de contextos de nível superior atualmente ativos. O aumento deste número ao longo do tempo indica um vazamento de memória.
number_of_detached_contexts
O valor de detached_context
é o número de contextos que foram separados e ainda não foram coletados como lixo. Este número ser diferente de zero indica um possível vazamento de memória.
total_global_handles_size
O valor de total_global_handles_size
é o tamanho total da memória das handles globais do V8.
used_global_handles_size
O valor de used_global_handles_size
é o tamanho da memória usada pelas handles globais do V8.
external_memory
O valor de external_memory
é o tamanho da memória de buffers de array e strings 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])
Adicionado em: v22.0.0, v20.13.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1.1 - Desenvolvimento ativo
ctor
<Function> O construtor que pode ser usado para pesquisar na cadeia de protótipos para filtrar objetos de destino no heap.options
<undefined> | <Object>format
<string> Se for'count'
, a contagem dos objetos correspondentes é retornada. Se for'summary'
, um array com strings de resumo dos objetos correspondentes é retornado.
Retorna: {number|Array
Isso é similar à API de console queryObjects()
fornecida pelo console do Chromium DevTools. Pode ser usado para pesquisar objetos que possuem o construtor correspondente em sua cadeia de protótipos no heap após uma coleta de lixo completa, o que pode ser útil para testes de regressão de vazamento de memória. Para evitar resultados surpreendentes, os usuários devem evitar usar essa API em construtores cuja implementação eles não controlam, ou em construtores que podem ser invocados por outras partes do aplicativo.
Para evitar vazamentos acidentais, esta API não retorna referências brutas aos objetos encontrados. Por padrão, ela retorna a contagem dos objetos encontrados. Se options.format
for 'summary'
, ela retorna um array contendo representações de string breves para cada objeto. A visibilidade fornecida nesta API é similar à que o snapshot do heap fornece, enquanto os usuários podem economizar o custo de serialização e análise e filtrar diretamente os objetos de destino durante a pesquisa.
Apenas objetos criados no contexto de execução atual são incluídos nos 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 que, quando há classes filhas herdando de um construtor,
// o construtor também aparece na cadeia de protótipos do protótipo da classe filha,
// então o protótipo da classe filha também seria
// incluído no resultado.
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 que, quando há classes filhas herdando de um construtor,
// o construtor também aparece na cadeia de protótipos do protótipo da classe filha,
// então o protótipo da classe filha também seria
// incluído no resultado.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))
v8.setFlagsFromString(flags)
Adicionado em: v1.0.0
flags
<string>
O método v8.setFlagsFromString()
pode ser usado para definir programaticamente flags de linha de comando do V8. Este método deve ser usado com cuidado. Alterar as configurações depois que a VM foi iniciada pode resultar em comportamento imprevisível, incluindo travamentos e perda de dados; ou simplesmente pode não fazer nada.
As opções V8 disponíveis para uma versão do Node.js podem ser determinadas executando node --v8-options
.
Uso:
// Imprime eventos GC para stdout por um minuto.
const v8 = require('node:v8')
v8.setFlagsFromString('--trace_gc')
setTimeout(() => {
v8.setFlagsFromString('--notrace_gc')
}, 60e3)
v8.stopCoverage()
Adicionado em: v15.1.0, v14.18.0, v12.22.0
O método v8.stopCoverage()
permite que o usuário pare a coleta de cobertura iniciada por NODE_V8_COVERAGE
, para que o V8 possa liberar os registros de contagem de execução e otimizar o código. Isso pode ser usado em conjunto com v8.takeCoverage()
se o usuário quiser coletar a cobertura sob demanda.
v8.takeCoverage()
Adicionado em: v15.1.0, v14.18.0, v12.22.0
O método v8.takeCoverage()
permite que o usuário grave a cobertura iniciada por NODE_V8_COVERAGE
no disco sob demanda. Este método pode ser invocado várias vezes durante a vida útil do processo. Cada vez, o contador de execução será redefinido e um novo relatório de cobertura será escrito para o diretório especificado por NODE_V8_COVERAGE
.
Quando o processo estiver prestes a sair, uma última cobertura ainda será escrita no disco, a menos que v8.stopCoverage()
seja invocado antes que o processo saia.
v8.writeHeapSnapshot([filename[,options]])
[Histórico]
Versão | Alterações |
---|---|
v19.1.0 | Suporte a opções para configurar o snapshot do heap. |
v18.0.0 | Uma exceção agora será lançada se o arquivo não puder ser escrito. |
v18.0.0 | Tornar os códigos de erro retornados consistentes em todas as plataformas. |
v11.13.0 | Adicionada em: v11.13.0 |
filename
<string> O caminho do arquivo onde o snapshot do heap V8 deve ser salvo. Se não especificado, um nome de arquivo com o padrão'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'
será gerado, onde{pid}
será o PID do processo Node.js,{thread_id}
será0
quandowriteHeapSnapshot()
for chamado do thread principal do Node.js ou o id de um thread worker.options
<Object>Retorna: <string> O nome do arquivo onde o snapshot foi salvo.
Gera um snapshot do heap V8 atual e o grava em um arquivo JSON. Este arquivo destina-se a ser usado com ferramentas como o Chrome DevTools. O esquema JSON não é documentado e é específico do mecanismo V8, e pode mudar de uma versão do V8 para a próxima.
Um snapshot de heap é específico para um único isolado V8. Ao usar threads worker, um snapshot de heap gerado a partir do thread principal não conterá nenhuma informação sobre os workers, e vice-versa.
Criar um snapshot de heap requer memória aproximadamente duas vezes o tamanho do heap no momento em que o snapshot é criado. Isso resulta no risco de terminadores OOM encerrando o processo.
Gerar um snapshot é uma operação síncrona que bloqueia o loop de eventos por uma duração dependendo do tamanho do heap.
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}`)
// Agora obtenha um heapdump para o thread principal.
console.log(`main thread heapdump: ${writeHeapSnapshot()}`)
})
// Diga ao worker para criar um heapdump.
worker.postMessage('heapdump')
} else {
parentPort.once('message', message => {
if (message === 'heapdump') {
// Gere um heapdump para o worker
// e retorne o nome do arquivo para o pai.
parentPort.postMessage(writeHeapSnapshot())
}
})
}
v8.setHeapSnapshotNearHeapLimit(limit)
Adicionado em: v18.10.0, v16.18.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1 - Experimental
limit
<inteiro>
A API é uma operação sem efeito se --heapsnapshot-near-heap-limit
já estiver definido a partir da linha de comando ou se a API for chamada mais de uma vez. limit
deve ser um inteiro positivo. Veja --heapsnapshot-near-heap-limit
para mais informações.
API de Serialização
A API de serialização fornece meios de serializar valores JavaScript de uma maneira compatível com o algoritmo de clone estruturado HTML.
O formato é retrocompatível (ou seja, seguro para armazenar em disco). Valores JavaScript iguais podem resultar em saídas serializadas diferentes.
v8.serialize(value)
Adicionado em: v8.0.0
value
<qualquer>- Retorna: <Buffer>
Usa um DefaultSerializer
para serializar value
em um buffer.
ERR_BUFFER_TOO_LARGE
será lançado ao tentar serializar um objeto enorme que requer um buffer maior que buffer.constants.MAX_LENGTH
.
v8.deserialize(buffer)
Adicionado em: v8.0.0
buffer
<Buffer> | <TypedArray> | <DataView> Um buffer retornado porserialize()
.
Usa um DefaultDeserializer
com opções padrão para ler um valor JS de um buffer.
Classe: v8.Serializer
Adicionado em: v8.0.0
new Serializer()
Cria um novo objeto Serializer
.
serializer.writeHeader()
Escreve um cabeçalho, que inclui a versão do formato de serialização.
serializer.writeValue(value)
value
<any>
Serializa um valor JavaScript e adiciona a representação serializada ao buffer interno.
Isso lança um erro se value
não puder ser serializado.
serializer.releaseBuffer()
- Retorna: <Buffer>
Retorna o buffer interno armazenado. Este serializador não deve ser usado após a liberação do buffer. Chamar este método resulta em comportamento indefinido se uma gravação anterior falhou.
serializer.transferArrayBuffer(id, arrayBuffer)
id
<integer> Um inteiro sem sinal de 32 bits.arrayBuffer
<ArrayBuffer> Uma instânciaArrayBuffer
.
Marca um ArrayBuffer
como tendo seu conteúdo transferido fora de banda. Passe o ArrayBuffer
correspondente no contexto de desserialização para deserializer.transferArrayBuffer()
.
serializer.writeUint32(value)
value
<integer>
Escreve um inteiro sem sinal de 32 bits bruto. Para uso dentro de um serializer._writeHostObject()
personalizado.
serializer.writeUint64(hi, lo)
Escreve um inteiro sem sinal de 64 bits bruto, dividido em partes altas e baixas de 32 bits. Para uso dentro de um serializer._writeHostObject()
personalizado.
serializer.writeDouble(value)
value
<number>
Escrever um valor number
JS. Para uso dentro de um serializer._writeHostObject()
personalizado.
serializer.writeRawBytes(buffer)
buffer
<Buffer> | <TypedArray> | <DataView>
Escrever bytes brutos no buffer interno do serializador. O desserializador precisará de uma maneira de calcular o comprimento do buffer. Para uso dentro de um serializer._writeHostObject()
personalizado.
serializer._writeHostObject(object)
object
<Object>
Este método é chamado para escrever algum tipo de objeto host, ou seja, um objeto criado por vinculações nativas C++. Se não for possível serializar object
, uma exceção adequada deve ser lançada.
Este método não está presente na própria classe Serializer
, mas pode ser fornecido por subclasses.
serializer._getDataCloneError(message)
message
<string>
Este método é chamado para gerar objetos de erro que serão lançados quando um objeto não puder ser clonado.
Este método é padrão para o construtor Error
e pode ser substituído em subclasses.
serializer._getSharedArrayBufferId(sharedArrayBuffer)
sharedArrayBuffer
<SharedArrayBuffer>
Este método é chamado quando o serializador vai serializar um objeto SharedArrayBuffer
. Ele deve retornar um ID inteiro de 32 bits sem sinal para o objeto, usando o mesmo ID se este SharedArrayBuffer
já foi serializado. Ao desserializar, este ID será passado para deserializer.transferArrayBuffer()
.
Se o objeto não puder ser serializado, uma exceção deve ser lançada.
Este método não está presente na própria classe Serializer
, mas pode ser fornecido por subclasses.
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
flag
<boolean> Padrão:false
Indica se os objetos TypedArray
e DataView
devem ser tratados como objetos host, ou seja, passados para serializer._writeHostObject()
.
Classe: v8.Deserializer
Adicionado em: v8.0.0
new Deserializer(buffer)
buffer
<Buffer> | <TypedArray> | <DataView> Um buffer retornado porserializer.releaseBuffer()
.
Cria um novo objeto Deserializer
.
deserializer.readHeader()
Lê e valida um cabeçalho (incluindo a versão do formato). Pode, por exemplo, rejeitar um formato de fio inválido ou não suportado. Nesse caso, um Error
é lançado.
deserializer.readValue()
Desserializa um valor JavaScript do buffer e o retorna.
deserializer.transferArrayBuffer(id, arrayBuffer)
id
<inteiro> Um inteiro sem sinal de 32 bits.arrayBuffer
<ArrayBuffer> | <SharedArrayBuffer> Uma instânciaArrayBuffer
.
Marca um ArrayBuffer
como tendo seu conteúdo transferido fora de banda. Passe o ArrayBuffer
correspondente no contexto de serialização para serializer.transferArrayBuffer()
(ou retorne o id
de serializer._getSharedArrayBufferId()
no caso de SharedArrayBuffer
s).
deserializer.getWireFormatVersion()
- Retorna: <inteiro>
Lê a versão subjacente do formato de transmissão. Provavelmente útil principalmente para código herdado que lê versões antigas do formato de transmissão. Pode não ser chamado antes de .readHeader()
.
deserializer.readUint32()
- Retorna: <inteiro>
Lê um inteiro sem sinal de 32 bits bruto e o retorna. Para uso dentro de um deserializer._readHostObject()
personalizado.
deserializer.readUint64()
- Retorna: <inteiro[]>
Lê um inteiro sem sinal de 64 bits bruto e o retorna como um array [hi, lo]
com duas entradas de inteiros sem sinal de 32 bits. Para uso dentro de um deserializer._readHostObject()
personalizado.
deserializer.readDouble()
- Retorna: <número>
Lê um valor number
do JS. Para uso dentro de um deserializer._readHostObject()
personalizado.
deserializer.readRawBytes(length)
Lê bytes brutos do buffer interno do deserializador. O parâmetro length
deve corresponder ao comprimento do buffer que foi passado para serializer.writeRawBytes()
. Para uso dentro de um deserializer._readHostObject()
personalizado.
deserializer._readHostObject()
Este método é chamado para ler algum tipo de objeto host, ou seja, um objeto criado por ligações nativas C++. Se não for possível desserializar os dados, uma exceção adequada deve ser lançada.
Este método não está presente na própria classe Deserializer
, mas pode ser fornecido por subclasses.
Classe: v8.DefaultSerializer
Adicionado em: v8.0.0
Uma subclasse de Serializer
que serializa objetos TypedArray
(em particular Buffer
) e DataView
como objetos host, e armazena apenas a parte de seus ArrayBuffer
s subjacentes aos quais eles estão referenciando.
Classe: v8.DefaultDeserializer
Adicionado em: v8.0.0
Uma subclasse de Deserializer
correspondente ao formato escrito por DefaultSerializer
.
Ganchos de Promise
A interface promiseHooks
pode ser usada para rastrear eventos do ciclo de vida da promise. Para rastrear toda a atividade assíncrona, consulte async_hooks
, que internamente usa este módulo para produzir eventos do ciclo de vida da promise, além de eventos para outros recursos assíncronos. Para gerenciamento de contexto de solicitação, consulte AsyncLocalStorage
.
import { promiseHooks } from 'node:v8'
// Existem quatro eventos do ciclo de vida produzidos por promises:
// O evento `init` representa a criação de uma promise. Isso pode ser uma
// criação direta, como com `new Promise(...)` ou uma continuação, como
// `then()` ou `catch()`. Também acontece sempre que uma função assíncrona é
// chamada ou faz um `await`. Se uma promise de continuação for criada, o
// `parent` será a promise da qual ela é uma continuação.
function init(promise, parent) {
console.log('uma promise foi criada', { promise, parent })
}
// O evento `settled` acontece quando uma promise recebe um valor de resolução ou
// rejeição. Isso pode acontecer sincronicamente, como quando se usa
// `Promise.resolve()` em entrada não-promise.
function settled(promise) {
console.log('uma promise foi resolvida ou rejeitada', { promise })
}
// O evento `before` é executado imediatamente antes de um manipulador `then()` ou `catch()`
// ser executado ou um `await` retomar a execução.
function before(promise) {
console.log('uma promise está prestes a chamar um manipulador then', { promise })
}
// O evento `after` é executado imediatamente após um manipulador `then()` ser executado ou quando
// um `await` começa após retomar de outro.
function after(promise) {
console.log('uma promise terminou de chamar um manipulador then', { promise })
}
// Ganchos do ciclo de vida podem ser iniciados e interrompidos individualmente
const stopWatchingInits = promiseHooks.onInit(init)
const stopWatchingSettleds = promiseHooks.onSettled(settled)
const stopWatchingBefores = promiseHooks.onBefore(before)
const stopWatchingAfters = promiseHooks.onAfter(after)
// Ou eles podem ser iniciados e interrompidos em grupos
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
})
// Para interromper um gancho, chame a função retornada em sua criação.
stopWatchingInits()
stopWatchingSettleds()
stopWatchingBefores()
stopWatchingAfters()
stopHookSet()
promiseHooks.onInit(init)
Adicionado em: v17.1.0, v16.14.0
init
<Function> O callbackinit
a ser chamado quando uma promise é criada.- Retorna: <Function> Chamada para parar o hook.
O hook init
deve ser uma função simples. Fornecer uma função assíncrona lançará uma exceção, pois isso produziria um loop infinito de microtarefas.
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)
Adicionado em: v17.1.0, v16.14.0
settled
<Function> O callbacksettled
a ser chamado quando uma promise é resolvida ou rejeitada.- Retorna: <Function> Chamada para parar o hook.
O hook settled
deve ser uma função simples. Fornecer uma função assíncrona lançará uma exceção, pois isso produziria um loop infinito de microtarefas.
import { promiseHooks } from 'node:v8'
const stop = promiseHooks.onSettled(promise => {})
const { promiseHooks } = require('node:v8')
const stop = promiseHooks.onSettled(promise => {})
promiseHooks.onBefore(before)
Adicionado em: v17.1.0, v16.14.0
before
<Function> O callbackbefore
a ser chamado antes da execução de uma continuação de promise.- Retorna: <Function> Chamada para parar o hook.
O hook before
deve ser uma função simples. Fornecer uma função assíncrona lançará uma exceção, pois isso produziria um loop infinito de microtarefas.
import { promiseHooks } from 'node:v8'
const stop = promiseHooks.onBefore(promise => {})
const { promiseHooks } = require('node:v8')
const stop = promiseHooks.onBefore(promise => {})
promiseHooks.onAfter(after)
Adicionado em: v17.1.0, v16.14.0
after
<Function> O callbackafter
a ser chamado após a execução de uma continuação de promise.- Retorna: <Function> Chamada para parar o hook.
O hook after
deve ser uma função simples. Fornecer uma função assíncrona lançará uma exceção, pois isso produziria um loop infinito de microtarefas.
import { promiseHooks } from 'node:v8'
const stop = promiseHooks.onAfter(promise => {})
const { promiseHooks } = require('node:v8')
const stop = promiseHooks.onAfter(promise => {})
promiseHooks.createHook(callbacks)
Adicionado em: v17.1.0, v16.14.0
callbacks
<Object> Os Callbacks do Hook a serem registradosinit
<Function> O callbackinit
.before
<Function> O callbackbefore
.after
<Function> O callbackafter
.settled
<Function> O callbacksettled
.
Retorna: <Function> Usado para desabilitar hooks
Os callbacks do hook devem ser funções simples. Fornecer funções assíncronas lançará uma exceção, pois isso produziria um loop infinito de microtarefas.
Registra funções a serem chamadas para diferentes eventos do ciclo de vida de cada promise.
Os callbacks init()
/before()
/after()
/settled()
são chamados para os respectivos eventos durante o ciclo de vida de uma promise.
Todos os callbacks são opcionais. Por exemplo, se apenas a criação de promise precisa ser rastreada, então apenas o callback init
precisa ser passado. As especificações de todas as funções que podem ser passadas para callbacks
estão na seção Callbacks do Hook.
import { promiseHooks } from 'node:v8'
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
})
const { promiseHooks } = require('node:v8')
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
})
Callbacks de Hook
Eventos-chave no ciclo de vida de uma promise foram categorizados em quatro áreas: criação de uma promise, antes/depois de um manipulador de continuação ser chamado ou em torno de um await, e quando a promise é resolvida ou rejeitada.
Embora esses hooks sejam semelhantes aos de async_hooks
, eles carecem de um hook destroy
. Outros tipos de recursos assíncronos tipicamente representam sockets ou descritores de arquivos que possuem um estado "fechado" distinto para expressar o evento de ciclo de vida destroy
, enquanto as promises permanecem utilizáveis enquanto o código ainda puder alcançá-las. O rastreamento de coleta de lixo é usado para fazer as promises se encaixarem no modelo de evento async_hooks
, no entanto, esse rastreamento é muito caro e elas podem não ser necessariamente coletadas pelo garbage collector.
Como as promises são recursos assíncronos cujo ciclo de vida é rastreado por meio do mecanismo de hooks de promise, os callbacks init()
, before()
, after()
, e settled()
não devem ser funções assíncronas, pois criam mais promises que produziriam um loop infinito.
Embora esta API seja usada para alimentar eventos de promise em async_hooks
, a ordem entre os dois é indefinida. Ambas as APIs são multi-tenant e, portanto, podem produzir eventos em qualquer ordem em relação uma à outra.
init(promise, parent)
promise
<Promise> A promise sendo criada.parent
<Promise> A promise continuada a partir de, se aplicável.
Chamado quando uma promise é construída. Isso não significa que os eventos before
/after
correspondentes ocorrerão, apenas que a possibilidade existe. Isso acontecerá se uma promise for criada sem nunca obter uma continuação.
before(promise)
promise
<Promise>
Chamado antes de uma continuação de promise ser executada. Isso pode estar na forma de manipuladores then()
, catch()
ou finally()
ou um await
sendo retomado.
O callback before
será chamado 0 a N vezes. O callback before
normalmente será chamado 0 vezes se nenhuma continuação foi feita para a promise. O callback before
pode ser chamado muitas vezes no caso em que muitas continuações foram feitas a partir da mesma promise.
after(promise)
promise
<Promise>
Chamado imediatamente após a execução de uma continuação de promise. Isso pode ser após um manipulador then()
, catch()
, ou finally()
ou antes de um await
após outro await
.
settled(promise)
promise
<Promise>
Chamado quando a promise recebe um valor de resolução ou rejeição. Isso pode ocorrer sincronicamente no caso de Promise.resolve()
ou Promise.reject()
.
API de Instantâneo de Inicialização
Adicionado em: v18.6.0, v16.17.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1 - Experimental
A interface v8.startupSnapshot
pode ser usada para adicionar ganchos de serialização e desserialização para instantâneos de inicialização personalizados.
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# Isso inicia um processo com o instantâneo {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob
No exemplo acima, entry.js
pode usar métodos da interface v8.startupSnapshot
para especificar como salvar informações para objetos personalizados no instantâneo durante a serialização e como as informações podem ser usadas para sincronizar esses objetos durante a desserialização do instantâneo. Por exemplo, se o entry.js
contiver o seguinte 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()
// Lendo uma série de arquivos do diretório e armazenando-os em 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 aqui é onde o script do instantâneo é colocado
// durante o tempo de construção do instantâneo.
const shelf = new BookShelf(__dirname, ['book1.en_US.txt', 'book1.es_ES.txt', 'book2.zh_CN.txt'])
assert(v8.startupSnapshot.isBuildingSnapshot())
// Na serialização do instantâneo, comprima os livros para reduzir o tamanho.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf)
// Na desserialização do instantâneo, descomprima os livros.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf)
v8.startupSnapshot.setDeserializeMainFunction(shelf => {
// process.env e process.argv são atualizados durante a desserialização do instantâneo.
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)
O binário resultante imprimirá os dados desserializados do instantâneo durante a inicialização, usando o process.env
e process.argv
atualizados do processo lançado:
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Imprime o conteúdo de book1.es_ES.txt desserializado do instantâneo. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}
Atualmente, o aplicativo desserializado de um instantâneo de espaço de usuário não pode ser instantâneo novamente, portanto, essas APIs estão disponíveis apenas para aplicativos que não são desserializados de um instantâneo de espaço de usuário.
v8.startupSnapshot.addSerializeCallback(callback[, data])
Adicionado em: v18.6.0, v16.17.0
callback
<Function> Função de retorno de chamada a ser invocada antes da serialização.data
<any> Dados opcionais que serão passados para acallback
quando ela for chamada.
Adicione uma função de retorno de chamada que será chamada quando a instância do Node.js estiver prestes a ser serializada em um snapshot e sair. Isso pode ser usado para liberar recursos que não devem ou não podem ser serializados ou para converter dados do usuário em uma forma mais adequada para serialização.
As funções de retorno de chamada são executadas na ordem em que são adicionadas.
v8.startupSnapshot.addDeserializeCallback(callback[, data])
Adicionado em: v18.6.0, v16.17.0
callback
<Function> Função de retorno de chamada a ser invocada após o snapshot ser desserializado.data
<any> Dados opcionais que serão passados para acallback
quando ela for chamada.
Adicione uma função de retorno de chamada que será chamada quando a instância do Node.js for desserializada de um snapshot. A callback
e os data
(se fornecidos) serão serializados no snapshot; eles podem ser usados para re-inicializar o estado do aplicativo ou para re-adquirir recursos de que o aplicativo precisa quando o aplicativo é reiniciado a partir do snapshot.
As funções de retorno de chamada são executadas na ordem em que são adicionadas.
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
Adicionado em: v18.6.0, v16.17.0
callback
<Function> Função de retorno de chamada a ser invocada como o ponto de entrada após o snapshot ser desserializado.data
<any> Dados opcionais que serão passados para acallback
quando ela for chamada.
Isso define o ponto de entrada do aplicativo Node.js quando ele é desserializado de um snapshot. Isso pode ser chamado apenas uma vez no script de criação do snapshot. Se chamado, o aplicativo desserializado não precisa mais de um script de ponto de entrada adicional para iniciar e simplesmente invocará a função de retorno de chamada juntamente com os dados desserializados (se fornecidos); caso contrário, um script de ponto de entrada ainda precisa ser fornecido ao aplicativo desserializado.
v8.startupSnapshot.isBuildingSnapshot()
Adicionado em: v18.6.0, v16.17.0
- Retorna: <boolean>
Retorna true
se a instância do Node.js está sendo executada para construir um snapshot.
Classe: v8.GCProfiler
Adicionado em: v19.6.0, v18.15.0
Esta API coleta dados de GC na thread atual.
new v8.GCProfiler()
Adicionado em: v19.6.0, v18.15.0
Cria uma nova instância da classe v8.GCProfiler
.
profiler.start()
Adicionado em: v19.6.0, v18.15.0
Inicia a coleta de dados de GC.
profiler.stop()
Adicionado em: v19.6.0, v18.15.0
Para a coleta de dados de GC e retorna um objeto. O conteúdo do objeto é o seguinte.
{
"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
}
Aqui está um exemplo.
const { GCProfiler } = require('node:v8')
const profiler = new GCProfiler()
profiler.start()
setTimeout(() => {
console.log(profiler.stop())
}, 1000)