V8
Codice sorgente: lib/v8.js
Il modulo node:v8
espone API specifiche per la versione di V8 integrata nel binario di Node.js. È possibile accedervi utilizzando:
const v8 = require('node:v8');
v8.cachedDataVersionTag()
Aggiunto in: v8.0.0
- Restituisce: <integer>
Restituisce un numero intero che rappresenta un tag di versione derivato dalla versione di V8, dai flag della riga di comando e dalle funzionalità della CPU rilevate. Ciò è utile per determinare se un buffer cachedData
di vm.Script
è compatibile con questa istanza di V8.
console.log(v8.cachedDataVersionTag()); // 3947234607
// Il valore restituito da v8.cachedDataVersionTag() deriva dalla versione di V8,
// dai flag della riga di comando e dalle funzionalità della CPU rilevate. Verifica
// che il valore si aggiorni effettivamente quando i flag vengono attivati/disattivati.
v8.setFlagsFromString('--allow_natives_syntax');
console.log(v8.cachedDataVersionTag()); // 183726201
v8.getHeapCodeStatistics()
Aggiunto in: v12.8.0
- Restituisce: <Object>
Ottiene statistiche sul codice e sui suoi metadati nell'heap, vedi l'API V8 GetHeapCodeAndMetadataStatistics
. Restituisce un oggetto con le seguenti proprietà:
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])
[Cronologia]
Versione | Modifiche |
---|---|
v19.1.0 | Supporta le opzioni per configurare l'istantanea dell'heap. |
v11.13.0 | Aggiunto in: v11.13.0 |
options
<Object>Restituisce: <stream.Readable> Un Readable contenente l'istantanea dell'heap V8.
Genera un'istantanea dell'heap V8 corrente e restituisce uno Stream Readable che può essere utilizzato per leggere la rappresentazione serializzata in JSON. Questo formato di flusso JSON è destinato all'uso con strumenti come Chrome DevTools. Lo schema JSON non è documentato ed è specifico del motore V8. Pertanto, lo schema potrebbe cambiare da una versione di V8 all'altra.
La creazione di un'istantanea dell'heap richiede una memoria di circa il doppio della dimensione dell'heap al momento della creazione dell'istantanea. Ciò comporta il rischio che i killer OOM terminino il processo.
La generazione di un'istantanea è un'operazione sincrona che blocca il ciclo di eventi per una durata dipendente dalla dimensione dell'heap.
// Stampa l'istantanea dell'heap sulla console
const v8 = require('node:v8');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout);
v8.getHeapSpaceStatistics()
[Cronologia]
Versione | Modifiche |
---|---|
v7.5.0 | Supporta valori che superano l'intervallo intero senza segno a 32 bit. |
v6.0.0 | Aggiunto in: v6.0.0 |
- Restituisce: <Object[]>
Restituisce statistiche sugli spazi heap V8, ovvero i segmenti che compongono l'heap V8. Né l'ordinamento degli spazi heap, né la disponibilità di uno spazio heap possono essere garantiti in quanto le statistiche sono fornite tramite la funzione V8 GetHeapSpaceStatistics
e potrebbero cambiare da una versione V8 all'altra.
Il valore restituito è un array di oggetti contenenti le seguenti proprietà:
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()
[Cronologia]
Versione | Modifiche |
---|---|
v7.5.0 | Supporta valori che superano l'intervallo di interi senza segno a 32 bit. |
v7.2.0 | Aggiunti malloced_memory , peak_malloced_memory e does_zap_garbage . |
v1.0.0 | Aggiunto in: v1.0.0 |
- Restituisce: <Object>
Restituisce un oggetto con le seguenti proprietà:
total_heap_size
<number>total_heap_size_executable
<number>total_physical_size
<number>total_available_size
<number>used_heap_size
<number>heap_size_limit
<number>malloced_memory
<number>peak_malloced_memory
<number>does_zap_garbage
<number>number_of_native_contexts
<number>number_of_detached_contexts
<number>total_global_handles_size
<number>used_global_handles_size
<number>external_memory
<number>
total_heap_size
Il valore di total_heap_size è il numero di byte che V8 ha allocato per l'heap. Questo può crescere se used_heap ha bisogno di più memoria.
total_heap_size_executable
Il valore di total_heap_size_executable è la porzione dell'heap che può contenere codice eseguibile, in byte. Questo include la memoria utilizzata dal codice compilato JIT e qualsiasi memoria che deve essere mantenuta eseguibile.
total_physical_size
Il valore di total_physical_size è la memoria fisica effettiva utilizzata dall'heap di V8, in byte. Questa è la quantità di memoria che è stata impegnata (o in uso) piuttosto che riservata.
total_available_size
Il valore di total_available_size è il numero di byte di memoria disponibile per l'heap di V8. Questo valore rappresenta quanta memoria in più V8 può utilizzare prima di superare il limite dell'heap.
used_heap_size
Il valore di used_heap_size è il numero di byte attualmente utilizzati dagli oggetti JavaScript di V8. Questa è la memoria effettiva in uso e non include la memoria che è stata allocata ma non ancora utilizzata.
heap_size_limit
Il valore di heap_size_limit è la dimensione massima dell'heap di V8, in byte (o il limite predefinito, determinato dalle risorse di sistema, o il valore passato all'opzione --max_old_space_size
).
malloced_memory
Il valore di malloced_memory è il numero di byte allocati tramite malloc
da V8.
peak_malloced_memory
Il valore di peak_malloced_memory è il numero massimo di byte allocati tramite malloc
da V8 durante la durata del processo.
does_zap_garbage
è un valore booleano 0/1, che indica se l'opzione --zap_code_space
è abilitata o meno. Questo fa sì che V8 sovrascriva la spazzatura dell'heap con un pattern di bit. L'impronta RSS (resident set size) diventa più grande perché tocca continuamente tutte le pagine dell'heap e questo le rende meno probabili da scambiare dal sistema operativo.
number_of_native_contexts
Il valore di native_context è il numero di contesti di livello superiore attualmente attivi. L'aumento di questo numero nel tempo indica una perdita di memoria.
number_of_detached_contexts
Il valore di detached_context è il numero di contesti che sono stati staccati e non ancora sottoposti a garbage collection. Questo numero diverso da zero indica una potenziale perdita di memoria.
total_global_handles_size
Il valore di total_global_handles_size è la dimensione totale della memoria degli handle globali V8.
used_global_handles_size
Il valore di used_global_handles_size è la dimensione della memoria utilizzata degli handle globali V8.
external_memory
Il valore di external_memory è la dimensione della memoria dei buffer di array e delle stringhe esterne.
{
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])
Aggiunto in: v22.0.0, v20.13.0
[Stable: 1 - Sperimentale]
Stable: 1 Stabilità: 1.1 - Sviluppo attivo
ctor
<Function> Il costruttore che può essere utilizzato per cercare nella catena del prototipo al fine di filtrare gli oggetti target nell'heap.options
<undefined> | <Object>format
<string> Se è'count'
, viene restituito il conteggio degli oggetti corrispondenti. Se è'summary'
, viene restituito un array con stringhe di riepilogo degli oggetti corrispondenti.
Restituisce: {number|Array
Questo è simile alla queryObjects()
console API fornita dalla console di Chromium DevTools. Può essere utilizzato per cercare oggetti che hanno il costruttore corrispondente nella sua catena del prototipo nell'heap dopo una garbage collection completa, il che può essere utile per i test di regressione delle perdite di memoria. Per evitare risultati sorprendenti, gli utenti dovrebbero evitare di utilizzare questa API su costruttori di cui non controllano l'implementazione o su costruttori che possono essere invocati da altre parti nell'applicazione.
Per evitare perdite accidentali, questa API non restituisce riferimenti raw agli oggetti trovati. Per impostazione predefinita, restituisce il conteggio degli oggetti trovati. Se options.format
è 'summary'
, restituisce un array contenente brevi rappresentazioni stringa per ciascun oggetto. La visibilità fornita in questa API è simile a quella fornita dallo snapshot dell'heap, mentre gli utenti possono risparmiare il costo della serializzazione e dell'analisi e filtrare direttamente gli oggetti target durante la ricerca.
Solo gli oggetti creati nel contesto di esecuzione corrente sono inclusi nei risultati.
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)
Aggiunto in: v1.0.0
flags
<stringa>
Il metodo v8.setFlagsFromString()
può essere utilizzato per impostare programmaticamente i flag della riga di comando di V8. Questo metodo dovrebbe essere usato con cautela. La modifica delle impostazioni dopo l'avvio della VM può comportare comportamenti imprevedibili, inclusi arresti anomali e perdita di dati; oppure potrebbe semplicemente non fare nulla.
Le opzioni V8 disponibili per una versione di Node.js possono essere determinate eseguendo node --v8-options
.
Utilizzo:
// Stampa gli eventi GC su stdout per un minuto.
const v8 = require('node:v8');
v8.setFlagsFromString('--trace_gc');
setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
v8.stopCoverage()
Aggiunto in: v15.1.0, v14.18.0, v12.22.0
Il metodo v8.stopCoverage()
consente all'utente di interrompere la raccolta della copertura iniziata da NODE_V8_COVERAGE
, in modo che V8 possa rilasciare i record del conteggio delle esecuzioni e ottimizzare il codice. Questo può essere usato in combinazione con v8.takeCoverage()
se l'utente vuole raccogliere la copertura su richiesta.
v8.takeCoverage()
Aggiunto in: v15.1.0, v14.18.0, v12.22.0
Il metodo v8.takeCoverage()
consente all'utente di scrivere su disco la copertura avviata da NODE_V8_COVERAGE
su richiesta. Questo metodo può essere invocato più volte durante la durata del processo. Ogni volta il contatore di esecuzione verrà resettato e un nuovo report di copertura verrà scritto nella directory specificata da NODE_V8_COVERAGE
.
Quando il processo sta per terminare, un'ultima copertura verrà comunque scritta su disco a meno che non venga invocato v8.stopCoverage()
prima che il processo termini.
v8.writeHeapSnapshot([filename[,options]])
[Cronologia]
Versione | Modifiche |
---|---|
v19.1.0 | Supporta opzioni per configurare l'heap snapshot. |
v18.0.0 | Ora verrà generata un'eccezione se il file non può essere scritto. |
v18.0.0 | Rendi i codici di errore restituiti coerenti su tutte le piattaforme. |
v11.13.0 | Aggiunto in: v11.13.0 |
filename
<stringa> Il percorso del file in cui deve essere salvato l'heap snapshot di V8. Se non specificato, verrà generato un nome file con il pattern'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'
, dove{pid}
sarà il PID del processo Node.js,{thread_id}
sarà0
quandowriteHeapSnapshot()
viene chiamato dal thread principale di Node.js o l'id di un thread worker.options
<Oggetto>exposeInternals
<booleano> Se true, espone gli interni nell'heap snapshot. Predefinito:false
.exposeNumericValues
<booleano> Se true, espone valori numerici in campi artificiali. Predefinito:false
.
Restituisce: <stringa> Il nome del file in cui è stato salvato lo snapshot.
Genera uno snapshot dell'heap V8 corrente e lo scrive in un file JSON. Questo file è destinato all'uso con strumenti come Chrome DevTools. Lo schema JSON non è documentato e specifico per il motore V8 e può cambiare da una versione di V8 all'altra.
Un heap snapshot è specifico per un singolo isolato V8. Quando si utilizzano i thread worker, un heap snapshot generato dal thread principale non conterrà alcuna informazione sui worker e viceversa.
La creazione di un heap snapshot richiede una memoria di circa il doppio della dimensione dell'heap al momento della creazione dello snapshot. Ciò comporta il rischio che gli OOM killer terminino il processo.
La generazione di uno snapshot è un'operazione sincrona che blocca l'event loop per una durata dipendente dalla dimensione dell'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}`);
// 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)
Aggiunto in: v18.10.0, v16.18.0
[Stabile: 1 - Sperimentale]
Stabile: 1 Stabilità: 1 - Sperimentale
limit
<integer>
L'API è un no-op se --heapsnapshot-near-heap-limit
è già stato impostato dalla riga di comando o se l'API viene chiamata più di una volta. limit
deve essere un numero intero positivo. Consulta --heapsnapshot-near-heap-limit
per maggiori informazioni.
API di serializzazione
L'API di serializzazione fornisce mezzi per serializzare i valori JavaScript in un modo compatibile con l'algoritmo di clonazione strutturata HTML.
Il formato è retrocompatibile (ovvero sicuro da memorizzare su disco). Valori JavaScript uguali possono produrre output serializzati diversi.
v8.serialize(value)
Aggiunto in: v8.0.0
Utilizza un DefaultSerializer
per serializzare value
in un buffer.
ERR_BUFFER_TOO_LARGE
verrà generato quando si tenta di serializzare un oggetto enorme che richiede un buffer più grande di buffer.constants.MAX_LENGTH
.
v8.deserialize(buffer)
Aggiunto in: v8.0.0
buffer
<Buffer> | <TypedArray> | <DataView> Un buffer restituito daserialize()
.
Utilizza un DefaultDeserializer
con opzioni predefinite per leggere un valore JS da un buffer.
Classe: v8.Serializer
Aggiunto in: v8.0.0
new Serializer()
Crea un nuovo oggetto Serializer
.
serializer.writeHeader()
Scrive un header, che include la versione del formato di serializzazione.
serializer.writeValue(value)
value
<any>
Serializza un valore JavaScript e aggiunge la rappresentazione serializzata al buffer interno.
Questo genera un errore se value
non può essere serializzato.
serializer.releaseBuffer()
- Restituisce: <Buffer>
Restituisce il buffer interno memorizzato. Questo serializzatore non deve essere utilizzato una volta che il buffer è stato rilasciato. La chiamata a questo metodo risulta in un comportamento indefinito se una scrittura precedente non è andata a buon fine.
serializer.transferArrayBuffer(id, arrayBuffer)
id
<integer> Un intero senza segno a 32 bit.arrayBuffer
<ArrayBuffer> Un'istanza diArrayBuffer
.
Marca un ArrayBuffer
come se il suo contenuto fosse stato trasferito fuori banda. Passa l' ArrayBuffer
corrispondente nel contesto di deserializzazione a deserializer.transferArrayBuffer()
.
serializer.writeUint32(value)
value
<integer>
Scrive un intero senza segno raw a 32 bit. Da utilizzare all'interno di un serializer._writeHostObject()
personalizzato.
serializer.writeUint64(hi, lo)
Scrive un intero senza segno raw a 64 bit, suddiviso in parti alte e basse a 32 bit. Da utilizzare all'interno di un serializer._writeHostObject()
personalizzato.
serializer.writeDouble(value)
value
<number>
Scrive un valore number
JS. Da utilizzare all'interno di un serializer._writeHostObject()
personalizzato.
serializer.writeRawBytes(buffer)
buffer
<Buffer> | <TypedArray> | <DataView>
Scrive byte raw nel buffer interno del serializzatore. Il deserializzatore richiederà un modo per calcolare la lunghezza del buffer. Da utilizzare all'interno di un serializer._writeHostObject()
personalizzato.
serializer._writeHostObject(object)
object
<Object>
Questo metodo viene chiamato per scrivere una sorta di oggetto host, ovvero un oggetto creato da binding C++ nativi. Se non è possibile serializzare object
, è necessario generare un'eccezione appropriata.
Questo metodo non è presente nella classe Serializer
stessa, ma può essere fornito dalle sottoclassi.
serializer._getDataCloneError(message)
message
<string>
Questo metodo viene chiamato per generare oggetti di errore che verranno generati quando un oggetto non può essere clonato.
Questo metodo è predefinito per il costruttore Error
e può essere sovrascritto sulle sottoclassi.
serializer._getSharedArrayBufferId(sharedArrayBuffer)
sharedArrayBuffer
<SharedArrayBuffer>
Questo metodo viene chiamato quando il serializzatore sta per serializzare un oggetto SharedArrayBuffer
. Deve restituire un ID intero a 32 bit senza segno per l'oggetto, utilizzando lo stesso ID se questo SharedArrayBuffer
è già stato serializzato. Durante la deserializzazione, questo ID verrà passato a deserializer.transferArrayBuffer()
.
Se l'oggetto non può essere serializzato, è necessario generare un'eccezione.
Questo metodo non è presente nella classe Serializer
stessa, ma può essere fornito dalle sottoclassi.
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
flag
<boolean> Predefinito:false
Indica se trattare gli oggetti TypedArray
e DataView
come oggetti host, ovvero passarli a serializer._writeHostObject()
.
Classe: v8.Deserializer
Aggiunto in: v8.0.0
new Deserializer(buffer)
buffer
<Buffer> | <TypedArray> | <DataView> Un buffer restituito daserializer.releaseBuffer()
.
Crea un nuovo oggetto Deserializer
.
deserializer.readHeader()
Legge e convalida un'intestazione (inclusa la versione del formato). Potrebbe, ad esempio, rifiutare un formato wire non valido o non supportato. In tal caso, viene generato un Error
.
deserializer.readValue()
Deserializza un valore JavaScript dal buffer e lo restituisce.
deserializer.transferArrayBuffer(id, arrayBuffer)
id
<integer> Un intero senza segno a 32 bit.arrayBuffer
<ArrayBuffer> | <SharedArrayBuffer> Un'istanza diArrayBuffer
.
Contrassegna un ArrayBuffer
come avente il suo contenuto trasferito fuori banda. Passare il corrispondente ArrayBuffer
nel contesto di serializzazione a serializer.transferArrayBuffer()
(o restituire l'id
da serializer._getSharedArrayBufferId()
nel caso di SharedArrayBuffer
).
deserializer.getWireFormatVersion()
- Restituisce: <integer>
Legge la versione del formato wire sottostante. Probabilmente utile soprattutto per il codice legacy che legge vecchie versioni del formato wire. Potrebbe non essere chiamato prima di .readHeader()
.
deserializer.readUint32()
- Restituisce: <integer>
Legge un intero senza segno raw a 32 bit e lo restituisce. Da utilizzare all'interno di un deserializer._readHostObject()
personalizzato.
deserializer.readUint64()
- Restituisce: <integer[]>
Legge un intero senza segno raw a 64 bit e lo restituisce come un array [hi, lo]
con due voci intere senza segno a 32 bit. Da utilizzare all'interno di un deserializer._readHostObject()
personalizzato.
deserializer.readDouble()
- Restituisce: <number>
Legge un valore number
JS. Da utilizzare all'interno di un deserializer._readHostObject()
personalizzato.
deserializer.readRawBytes(length)
Legge byte raw dal buffer interno del deserializzatore. Il parametro length
deve corrispondere alla lunghezza del buffer che è stato passato a serializer.writeRawBytes()
. Da utilizzare all'interno di un deserializer._readHostObject()
personalizzato.
deserializer._readHostObject()
Questo metodo viene chiamato per leggere un qualche tipo di oggetto host, ovvero un oggetto creato da binding C++ nativi. Se non è possibile deserializzare i dati, dovrebbe essere generata un'eccezione appropriata.
Questo metodo non è presente nella classe Deserializer
stessa, ma può essere fornito dalle sottoclassi.
Classe: v8.DefaultSerializer
Aggiunto in: v8.0.0
Una sottoclasse di Serializer
che serializza gli oggetti TypedArray
(in particolare Buffer
) e DataView
come oggetti host, e memorizza solo la parte dei loro ArrayBuffer
sottostanti a cui si riferiscono.
Classe: v8.DefaultDeserializer
Aggiunto in: v8.0.0
Una sottoclasse di Deserializer
corrispondente al formato scritto da DefaultSerializer
.
Hook delle Promise
L'interfaccia promiseHooks
può essere utilizzata per tenere traccia degli eventi del ciclo di vita delle promise. Per tenere traccia di tutta l'attività asincrona, consulta async_hooks
che internamente utilizza questo modulo per produrre eventi del ciclo di vita delle promise in aggiunta agli eventi per altre risorse asincrone. Per la gestione del contesto delle richieste, consulta AsyncLocalStorage
.
import { promiseHooks } from 'node:v8';
// Ci sono quattro eventi del ciclo di vita prodotti dalle promise:
// L'evento `init` rappresenta la creazione di una promise. Questa potrebbe essere
// una creazione diretta come con `new Promise(...)` o una continuazione come
// `then()` o `catch()`. Succede anche ogni volta che una funzione async viene
// chiamata o fa un `await`. Se viene creata una promise di continuazione, il
// `parent` sarà la promise da cui è una continuazione.
function init(promise, parent) {
console.log('una promise è stata creata', { promise, parent });
}
// L'evento `settled` si verifica quando una promise riceve una risoluzione o
// un valore di rifiuto. Questo può accadere in modo sincrono come quando si usa
// `Promise.resolve()` su input non promise.
function settled(promise) {
console.log('una promise è stata risolta o rifiutata', { promise });
}
// L'evento `before` viene eseguito immediatamente prima che venga eseguito un gestore `then()` o `catch()`
// o una `await` riprenda l'esecuzione.
function before(promise) {
console.log('una promise sta per chiamare un gestore then', { promise });
}
// L'evento `after` viene eseguito immediatamente dopo che viene eseguito un gestore `then()` o quando
// un `await` inizia dopo la ripresa da un altro.
function after(promise) {
console.log('una promise ha finito di chiamare un gestore then', { promise });
}
// Gli hook del ciclo di vita possono essere avviati e arrestati individualmente
const stopWatchingInits = promiseHooks.onInit(init);
const stopWatchingSettleds = promiseHooks.onSettled(settled);
const stopWatchingBefores = promiseHooks.onBefore(before);
const stopWatchingAfters = promiseHooks.onAfter(after);
// Oppure possono essere avviati e arrestati in gruppi
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
});
// Per interrompere un hook, chiama la funzione restituita alla sua creazione.
stopWatchingInits();
stopWatchingSettleds();
stopWatchingBefores();
stopWatchingAfters();
stopHookSet();
promiseHooks.onInit(init)
Aggiunto in: v17.1.0, v16.14.0
init
<Function> Ilcallback init
da chiamare quando viene creata una promise.- Restituisce: <Function> Chiama per interrompere l'hook.
L'hook init
deve essere una funzione semplice. Fornire una funzione async genererà un'eccezione poiché produrrebbe un loop infinito di microtask.
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)
Aggiunto in: v17.1.0, v16.14.0
settled
<Function> Ilcallback settled
da chiamare quando una promise viene risolta o rifiutata.- Restituisce: <Function> Chiama per interrompere l'hook.
L'hook settled
deve essere una funzione semplice. Fornire una funzione async genererà un'eccezione poiché produrrebbe un loop infinito di microtask.
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onSettled((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onSettled((promise) => {});
promiseHooks.onBefore(before)
Aggiunto in: v17.1.0, v16.14.0
before
<Function> Ilcallback before
da chiamare prima che venga eseguita una continuazione della promise.- Restituisce: <Function> Chiama per interrompere l'hook.
L'hook before
deve essere una funzione semplice. Fornire una funzione async genererà un'eccezione poiché produrrebbe un loop infinito di microtask.
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onBefore((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onBefore((promise) => {});
promiseHooks.onAfter(after)
Aggiunto in: v17.1.0, v16.14.0
after
<Function> Lacallback after
da chiamare dopo che un continuation di una promise viene eseguito.- Restituisce: <Function> Chiama per fermare l'hook.
L'hook after
deve essere una funzione semplice. Fornire una funzione asincrona genererà un'eccezione in quanto produrrebbe un ciclo infinito di microtask.
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onAfter((promise) => {});
const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onAfter((promise) => {});
promiseHooks.createHook(callbacks)
Aggiunto in: v17.1.0, v16.14.0
callbacks
<Object> Le Hook Callbacks da registrareinit
<Function> Lacallback init
.before
<Function> Lacallback before
.after
<Function> Lacallback after
.settled
<Function> Lacallback settled
.
Restituisce: <Function> Usato per disabilitare gli hook
Le hook callbacks devono essere funzioni semplici. Fornire funzioni asincrone genererà un'eccezione in quanto produrrebbe un ciclo infinito di microtask.
Registra le funzioni da chiamare per diversi eventi del ciclo di vita di ogni promise.
Le callbacks init()
/before()
/after()
/settled()
vengono chiamate per i rispettivi eventi durante il ciclo di vita di una promise.
Tutte le callbacks sono opzionali. Ad esempio, se è necessario tracciare solo la creazione di una promise, allora deve essere passata solo la callback init
. Le specifiche di tutte le funzioni che possono essere passate a callbacks
si trovano nella sezione 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) {},
});
Hook callbacks
Gli eventi chiave nel ciclo di vita di una promise sono stati suddivisi in quattro aree: creazione di una promise, prima/dopo che viene chiamato un gestore di continuazione o intorno a un await, e quando la promise si risolve o viene rifiutata.
Sebbene questi hook siano simili a quelli di async_hooks
mancano di un hook destroy
. Altri tipi di risorse asincrone rappresentano in genere socket o descrittori di file che hanno un distinto stato "chiuso" per esprimere l'evento del ciclo di vita destroy
mentre le promise rimangono utilizzabili fintanto che il codice può ancora raggiungerle. Il tracciamento della garbage collection viene utilizzato per adattare le promise al modello di evento async_hooks
, tuttavia questo tracciamento è molto costoso e potrebbero non essere nemmeno mai sottoposte a garbage collection.
Poiché le promise sono risorse asincrone il cui ciclo di vita viene tracciato tramite il meccanismo degli hook delle promise, i callback init()
, before()
, after()
e settled()
non devono essere funzioni asincrone poiché creano più promise che produrrebbero un ciclo infinito.
Sebbene questa API venga utilizzata per alimentare gli eventi delle promise in async_hooks
, l'ordine tra i due non è definito. Entrambe le API sono multi-tenant e quindi potrebbero produrre eventi in qualsiasi ordine l'una rispetto all'altra.
init(promise, parent)
promise
<Promise> La promise che viene creata.parent
<Promise> La promise continuata da, se applicabile.
Chiamato quando viene costruita una promise. Questo non significa che si verificheranno eventi before
/after
corrispondenti, solo che esiste la possibilità. Ciò accadrà se una promise viene creata senza mai ottenere una continuazione.
before(promise)
promise
<Promise>
Chiamato prima che venga eseguita una continuazione della promise. Questa può essere sotto forma di gestori then()
, catch()
o finally()
o di una ripresa await
.
Il callback before
verrà chiamato da 0 a N volte. Il callback before
verrà in genere chiamato 0 volte se non è mai stata effettuata alcuna continuazione per la promise. Il callback before
può essere chiamato molte volte nel caso in cui siano state effettuate molte continuazioni dalla stessa promise.
after(promise)
promise
<Promise>
Chiamato immediatamente dopo l'esecuzione di una continuazione di una promise. Questo può avvenire dopo un gestore then()
, catch()
o finally()
oppure prima di un await
dopo un altro await
.
settled(promise)
promise
<Promise>
Chiamato quando la promise riceve un valore di risoluzione o rifiuto. Ciò può verificarsi in modo sincrono nel caso di Promise.resolve()
o Promise.reject()
.
API Snapshot di Avvio
Aggiunto in: v18.6.0, v16.17.0
[Stabile: 1 - Sperimentale]
Stabile: 1 Stabilità: 1 - Sperimentale
L'interfaccia v8.startupSnapshot
può essere utilizzata per aggiungere hook di serializzazione e deserializzazione per snapshot di avvio personalizzati.
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# Questo avvia un processo con lo snapshot {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob
Nell'esempio sopra, entry.js
può utilizzare i metodi dell'interfaccia v8.startupSnapshot
per specificare come salvare le informazioni per oggetti personalizzati nello snapshot durante la serializzazione e come le informazioni possono essere utilizzate per sincronizzare questi oggetti durante la deserializzazione dello snapshot. Ad esempio, se entry.js
contiene il seguente 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();
// Lettura di una serie di file dalla directory e memorizzazione in 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 qui è dove viene posizionato lo script snapshot
// durante il tempo di costruzione dello snapshot.
const shelf = new BookShelf(__dirname, [
'book1.en_US.txt',
'book1.es_ES.txt',
'book2.zh_CN.txt',
]);
assert(v8.startupSnapshot.isBuildingSnapshot());
// Durante la serializzazione dello snapshot, comprimi i libri per ridurre le dimensioni.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf);
// Durante la deserializzazione dello snapshot, decomprimi i libri.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf);
v8.startupSnapshot.setDeserializeMainFunction((shelf) => {
// process.env e process.argv vengono aggiornati durante lo snapshot
// deserializzazione.
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);
Il binario risultante stamperà i dati deserializzati dallo snapshot durante l'avvio, utilizzando process.env
e process.argv
aggiornati del processo avviato:
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Stampa il contenuto di book1.es_ES.txt deserializzato dallo snapshot. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}
Attualmente, l'applicazione deserializzata da uno snapshot user-land non può essere nuovamente sottoposta a snapshot, quindi queste API sono disponibili solo per le applicazioni che non sono deserializzate da uno snapshot user-land.
v8.startupSnapshot.addSerializeCallback(callback[, data])
Aggiunto in: v18.6.0, v16.17.0
callback
<Function> Callback da invocare prima della serializzazione.data
<any> Dati opzionali che verranno passati allacallback
quando viene chiamata.
Aggiunge una callback che verrà chiamata quando l'istanza di Node.js sta per essere serializzata in uno snapshot ed uscire. Questo può essere utilizzato per rilasciare risorse che non dovrebbero o non possono essere serializzate o per convertire i dati dell'utente in una forma più adatta alla serializzazione.
Le callback vengono eseguite nell'ordine in cui vengono aggiunte.
v8.startupSnapshot.addDeserializeCallback(callback[, data])
Aggiunto in: v18.6.0, v16.17.0
callback
<Function> Callback da invocare dopo che lo snapshot è stato deserializzato.data
<any> Dati opzionali che verranno passati allacallback
quando viene chiamata.
Aggiunge una callback che verrà chiamata quando l'istanza di Node.js viene deserializzata da uno snapshot. La callback
ed i data
(se forniti) verranno serializzati nello snapshot, possono essere utilizzati per reinizializzare lo stato dell'applicazione o per riacquisire le risorse di cui l'applicazione ha bisogno quando l'applicazione viene riavviata dallo snapshot.
Le callback vengono eseguite nell'ordine in cui vengono aggiunte.
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
Aggiunto in: v18.6.0, v16.17.0
callback
<Function> Callback da invocare come punto di ingresso dopo che lo snapshot è stato deserializzato.data
<any> Dati opzionali che verranno passati allacallback
quando viene chiamata.
Questo imposta il punto di ingresso dell'applicazione Node.js quando viene deserializzata da uno snapshot. Questo può essere chiamato una sola volta nello script di creazione dello snapshot. Se chiamato, l'applicazione deserializzata non ha più bisogno di uno script di punto di ingresso aggiuntivo per avviarsi e invocherà semplicemente la callback insieme ai dati deserializzati (se forniti), altrimenti è necessario fornire comunque uno script di punto di ingresso all'applicazione deserializzata.
v8.startupSnapshot.isBuildingSnapshot()
Aggiunto in: v18.6.0, v16.17.0
- Restituisce: <boolean>
Restituisce true se l'istanza di Node.js viene eseguita per creare uno snapshot.
Classe: v8.GCProfiler
Aggiunto in: v19.6.0, v18.15.0
Questa API raccoglie i dati GC nel thread corrente.
new v8.GCProfiler()
Aggiunto in: v19.6.0, v18.15.0
Crea una nuova istanza della classe v8.GCProfiler
.
profiler.start()
Aggiunto in: v19.6.0, v18.15.0
Inizia a raccogliere i dati GC.
profiler.stop()
Aggiunto in: v19.6.0, v18.15.0
Interrompe la raccolta dei dati GC e restituisce un oggetto. Il contenuto dell'oggetto è il seguente.
{
"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
}
Ecco un esempio.
const { GCProfiler } = require('node:v8');
const profiler = new GCProfiler();
profiler.start();
setTimeout(() => {
console.log(profiler.stop());
}, 1000);