V8
Code source : lib/v8.js
Le module node:v8
expose des API spécifiques à la version de V8 intégrée au binaire Node.js. Il est accessible via :
const v8 = require('node:v8')
v8.cachedDataVersionTag()
Ajouté dans : v8.0.0
- Retourne : <entier>
Retourne un entier représentant une balise de version dérivée de la version de V8, des drapeaux de ligne de commande et des fonctionnalités CPU détectées. Ceci est utile pour déterminer si un tampon cachedData
de vm.Script
est compatible avec cette instance de V8.
console.log(v8.cachedDataVersionTag()) // 3947234607
// La valeur retournée par v8.cachedDataVersionTag() est dérivée de la version de V8,
// des drapeaux de ligne de commande et des fonctionnalités CPU détectées. Vérifiez que la valeur
// est bien mise à jour lorsque les drapeaux sont modifiés.
v8.setFlagsFromString('--allow_natives_syntax')
console.log(v8.cachedDataVersionTag()) // 183726201
v8.getHeapCodeStatistics()
Ajouté dans : v12.8.0
- Retourne : <Objet>
Obtenir des statistiques sur le code et ses métadonnées dans le tas, voir l'API V8 GetHeapCodeAndMetadataStatistics
. Retourne un objet avec les propriétés suivantes :
code_and_metadata_size
<nombre>bytecode_and_metadata_size
<nombre>external_script_source_size
<nombre>cpu_profiler_metadata_size
<nombre>
{
code_and_metadata_size: 212208,
bytecode_and_metadata_size: 161368,
external_script_source_size: 1410794,
cpu_profiler_metadata_size: 0,
}
v8.getHeapSnapshot([options])
[Historique]
Version | Modifications |
---|---|
v19.1.0 | Prise en charge des options pour configurer l'instantané du tas. |
v11.13.0 | Ajouté dans : v11.13.0 |
options
<Objet>Retourne : <stream.Readable> Un flux lisible contenant l'instantané du tas V8.
Génère un instantané du tas V8 actuel et renvoie un flux lisible qui peut être utilisé pour lire la représentation sérialisée JSON. Ce format de flux JSON est destiné à être utilisé avec des outils tels que Chrome DevTools. Le schéma JSON n'est pas documenté et est spécifique au moteur V8. Par conséquent, le schéma peut changer d'une version de V8 à l'autre.
La création d'un instantané du tas nécessite une mémoire environ deux fois plus grande que la taille du tas au moment de la création de l'instantané. Cela entraîne un risque que les tueurs OOM mettent fin au processus.
La génération d'un instantané est une opération synchrone qui bloque la boucle d'événements pendant une durée dépendant de la taille du tas.
// Afficher l'instantané du tas sur la console
const v8 = require('node:v8')
const stream = v8.getHeapSnapshot()
stream.pipe(process.stdout)
v8.getHeapSpaceStatistics()
[Historique]
Version | Modifications |
---|---|
v7.5.0 | Prise en charge des valeurs dépassant la plage des entiers non signés 32 bits. |
v6.0.0 | Ajouté dans : v6.0.0 |
- Retourne : <Objet[]>
Renvoie des statistiques sur les espaces de tas V8, c'est-à-dire les segments qui composent le tas V8. Ni l'ordre des espaces de tas, ni la disponibilité d'un espace de tas ne peuvent être garantis, car les statistiques sont fournies via la fonction V8 GetHeapSpaceStatistics
et peuvent changer d'une version V8 à l'autre.
La valeur renvoyée est un tableau d'objets contenant les propriétés suivantes :
space_name
<chaîne de caractères>space_size
<nombre>space_used_size
<nombre>space_available_size
<nombre>physical_space_size
<nombre>
[
{
"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()
[Historique]
Version | Modifications |
---|---|
v7.5.0 | Prise en charge des valeurs dépassant la plage des entiers non signés 32 bits. |
v7.2.0 | Ajout de malloced_memory , peak_malloced_memory , et does_zap_garbage . |
v1.0.0 | Ajouté dans : v1.0.0 |
- Retourne : <Objet>
Retourne un objet avec les propriétés suivantes :
total_heap_size
<nombre>total_heap_size_executable
<nombre>total_physical_size
<nombre>total_available_size
<nombre>used_heap_size
<nombre>heap_size_limit
<nombre>malloced_memory
<nombre>peak_malloced_memory
<nombre>does_zap_garbage
<nombre>number_of_native_contexts
<nombre>number_of_detached_contexts
<nombre>total_global_handles_size
<nombre>used_global_handles_size
<nombre>external_memory
<nombre>
total_heap_size
La valeur de total_heap_size
est le nombre d'octets que V8 a alloués pour le tas. Cela peut augmenter si used_heap
a besoin de plus de mémoire.
total_heap_size_executable
La valeur de total_heap_size_executable
est la partie du tas qui peut contenir du code exécutable, en octets. Cela inclut la mémoire utilisée par le code compilé JIT et toute mémoire qui doit rester exécutable.
total_physical_size
La valeur de total_physical_size
est la mémoire physique réelle utilisée par le tas V8, en octets. Il s'agit de la quantité de mémoire qui est allouée (ou utilisée) plutôt que réservée.
total_available_size
La valeur de total_available_size
est le nombre d'octets de mémoire disponibles pour le tas V8. Cette valeur représente la quantité de mémoire supplémentaire que V8 peut utiliser avant de dépasser la limite du tas.
used_heap_size
La valeur de used_heap_size
est le nombre d'octets actuellement utilisés par les objets JavaScript de V8. Il s'agit de la mémoire réellement utilisée et n'inclut pas la mémoire qui a été allouée mais pas encore utilisée.
heap_size_limit
La valeur de heap_size_limit
est la taille maximale du tas V8, en octets (soit la limite par défaut, déterminée par les ressources système, soit la valeur passée à l'option --max_old_space_size
).
malloced_memory
La valeur de malloced_memory
est le nombre d'octets alloués via malloc
par V8.
peak_malloced_memory
La valeur de peak_malloced_memory
est le nombre maximal d'octets alloués via malloc
par V8 pendant la durée de vie du processus.
does_zap_garbage
est un booléen 0/1, qui indique si l'option --zap_code_space
est activée ou non. Cela fait que V8 écrase les ordures du tas avec un motif binaire. L'empreinte RSS (taille du jeu résident) augmente car elle touche continuellement toutes les pages du tas et cela les rend moins susceptibles d'être échangées par le système d'exploitation.
number_of_native_contexts
La valeur de native_context
est le nombre de contextes de niveau supérieur actuellement actifs. L'augmentation de ce nombre au fil du temps indique une fuite de mémoire.
number_of_detached_contexts
La valeur de detached_context
est le nombre de contextes qui ont été détachés et qui n'ont pas encore été collectés par le garbage collector. Ce nombre étant non nul indique une fuite de mémoire potentielle.
total_global_handles_size
La valeur de total_global_handles_size
est la taille mémoire totale des handles globaux V8.
used_global_handles_size
La valeur de used_global_handles_size
est la taille mémoire utilisée des handles globaux V8.
external_memory
La valeur de external_memory
est la taille mémoire des tableaux tampon et des chaînes externes.
{
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])
Ajouté dans : v22.0.0, v20.13.0
[Stable : 1 - Expérimental]
Stable : 1 Stabilité : 1.1 - Développement actif
ctor
<Function> Le constructeur pouvant être utilisé pour rechercher sur la chaîne de prototypes afin de filtrer les objets cibles dans le tas.options
<undefined> | <Object>format
<string> Si c'est'count'
, le nombre d'objets correspondants est renvoyé. Si c'est'summary'
, un tableau contenant des chaînes de résumé des objets correspondants est renvoyé.
Retourne : {number|Array
Ceci est similaire à l'API console queryObjects()
fournie par la console Chromium DevTools. Elle peut être utilisée pour rechercher des objets ayant le constructeur correspondant sur leur chaîne de prototypes dans le tas après un ramassage des ordures complet, ce qui peut être utile pour les tests de régression de fuite de mémoire. Pour éviter des résultats surprenants, les utilisateurs doivent éviter d'utiliser cette API sur des constructeurs dont ils ne contrôlent pas l'implémentation, ou sur des constructeurs qui peuvent être invoqués par d'autres parties de l'application.
Pour éviter les fuites accidentelles, cette API ne renvoie pas de références brutes aux objets trouvés. Par défaut, elle renvoie le nombre d'objets trouvés. Si options.format
est 'summary'
, elle renvoie un tableau contenant de brèves représentations sous forme de chaînes de caractères pour chaque objet. La visibilité fournie dans cette API est similaire à celle fournie par l'instantané du tas, tandis que les utilisateurs peuvent économiser le coût de la sérialisation et de l'analyse et filtrer directement les objets cibles pendant la recherche.
Seuls les objets créés dans le contexte d'exécution actuel sont inclus dans les résultats.
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' }))
// Notez que, lorsqu'il existe des classes enfants héritant d'un constructeur,
// le constructeur apparaît également dans la chaîne de prototypes du prototype des classes enfants,
// donc le prototype des classes enfants serait également inclus dans le résultat.
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' }))
// Notez que, lorsqu'il existe des classes enfants héritant d'un constructeur,
// le constructeur apparaît également dans la chaîne de prototypes du prototype des classes enfants,
// donc le prototype des classes enfants serait également inclus dans le résultat.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))
v8.setFlagsFromString(flags)
Ajouté dans : v1.0.0
flags
<string>
La méthode v8.setFlagsFromString()
permet de définir par programme les indicateurs de ligne de commande de V8. Cette méthode doit être utilisée avec précaution. La modification des paramètres après le démarrage de la machine virtuelle peut entraîner un comportement imprévisible, notamment des plantages et des pertes de données ; ou cela peut simplement ne rien faire.
Les options V8 disponibles pour une version de Node.js peuvent être déterminées en exécutant node --v8-options
.
Utilisation :
// Imprimer les événements GC sur stdout pendant une minute.
const v8 = require('node:v8')
v8.setFlagsFromString('--trace_gc')
setTimeout(() => {
v8.setFlagsFromString('--notrace_gc')
}, 60e3)
v8.stopCoverage()
Ajouté dans : v15.1.0, v14.18.0, v12.22.0
La méthode v8.stopCoverage()
permet à l’utilisateur d’arrêter la collecte de la couverture lancée par NODE_V8_COVERAGE
, afin que V8 puisse libérer les enregistrements de comptage d’exécution et optimiser le code. Cela peut être utilisé conjointement avec v8.takeCoverage()
si l’utilisateur souhaite collecter la couverture à la demande.
v8.takeCoverage()
Ajouté dans : v15.1.0, v14.18.0, v12.22.0
La méthode v8.takeCoverage()
permet à l’utilisateur d’écrire la couverture lancée par NODE_V8_COVERAGE
sur le disque à la demande. Cette méthode peut être invoquée plusieurs fois pendant la durée de vie du processus. À chaque fois, le compteur d’exécution sera réinitialisé et un nouveau rapport de couverture sera écrit dans le répertoire spécifié par NODE_V8_COVERAGE
.
Lorsque le processus est sur le point de se terminer, une dernière couverture sera toujours écrite sur le disque, sauf si v8.stopCoverage()
est invoquée avant la fin du processus.
v8.writeHeapSnapshot([filename[,options]])
[Historique]
Version | Modifications |
---|---|
v19.1.0 | Prise en charge des options pour configurer l’instantané du tas. |
v18.0.0 | Une exception sera désormais levée si le fichier n’a pas pu être écrit. |
v18.0.0 | Rendre les codes d’erreur retournés cohérents sur toutes les plateformes. |
v11.13.0 | Ajouté dans : v11.13.0 |
filename
<string> Le chemin du fichier où l’instantané du tas V8 doit être enregistré. Si ce n’est pas spécifié, un nom de fichier avec le modèle'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'
sera généré, où{pid}
sera le PID du processus Node.js,{thread_id}
sera0
lorsquewriteHeapSnapshot()
est appelé à partir du thread principal Node.js ou l’ID d’un thread de travailleur.options
<Object>Retourne : <string> Le nom du fichier où l’instantané a été enregistré.
Génère un instantané du tas V8 actuel et l’écrit dans un fichier JSON. Ce fichier est destiné à être utilisé avec des outils tels que Chrome DevTools. Le schéma JSON n’est pas documenté et est spécifique au moteur V8, et peut changer d’une version de V8 à l’autre.
Un instantané du tas est spécifique à un seul isolat V8. Lorsque vous utilisez des threads de travailleur, un instantané du tas généré à partir du thread principal ne contiendra aucune information sur les travailleurs, et vice versa.
La création d’un instantané du tas nécessite une mémoire environ deux fois plus grande que la taille du tas au moment de la création de l’instantané. Cela entraîne un risque de terminaison du processus par les tueurs OOM.
La génération d’un instantané est une opération synchrone qui bloque la boucle d’événements pendant une durée dépendant de la taille du tas.
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}`)
// Maintenant, obtenez un heapdump pour le thread principal.
console.log(`main thread heapdump: ${writeHeapSnapshot()}`)
})
// Dire au travailleur de créer un heapdump.
worker.postMessage('heapdump')
} else {
parentPort.once('message', message => {
if (message === 'heapdump') {
// Générer un heapdump pour le travailleur
// et renvoyer le nom de fichier au parent.
parentPort.postMessage(writeHeapSnapshot())
}
})
}
v8.setHeapSnapshotNearHeapLimit(limit)
Ajouté dans : v18.10.0, v16.18.0
[Stable : 1 - Expérimental]
Stable : 1 Stabilité : 1 - Expérimental
limit
<entier>
L'API est une opération sans effet si --heapsnapshot-near-heap-limit
est déjà défini depuis la ligne de commande ou si l'API est appelée plus d'une fois. limit
doit être un entier positif. Voir --heapsnapshot-near-heap-limit
pour plus d'informations.
API de sérialisation
L'API de sérialisation fournit des moyens de sérialiser des valeurs JavaScript d'une manière compatible avec l'algorithme de clonage structuré HTML.
Le format est rétrocompatible (c'est-à-dire qu'il est sûr de le stocker sur le disque). Des valeurs JavaScript égales peuvent donner des résultats de sérialisation différents.
v8.serialize(value)
Ajouté dans : v8.0.0
Utilise un DefaultSerializer
pour sérialiser value
dans une mémoire tampon.
ERR_BUFFER_TOO_LARGE
sera levée lors de la tentative de sérialisation d'un objet volumineux nécessitant une mémoire tampon supérieure à buffer.constants.MAX_LENGTH
.
v8.deserialize(buffer)
Ajouté dans : v8.0.0
buffer
<Buffer> | <TypedArray> | <DataView> Une mémoire tampon renvoyée parserialize()
.
Utilise un DefaultDeserializer
avec les options par défaut pour lire une valeur JS à partir d'une mémoire tampon.
Classe : v8.Serializer
Ajouté dans : v8.0.0
new Serializer()
Crée un nouvel objet Serializer
.
serializer.writeHeader()
Écrit un en-tête, qui inclut la version du format de sérialisation.
serializer.writeValue(value)
value
<any>
Sérialise une valeur JavaScript et ajoute la représentation sérialisée au tampon interne.
Ceci lève une erreur si value
ne peut pas être sérialisé.
serializer.releaseBuffer()
- Retourne : <Buffer>
Retourne le tampon interne stocké. Ce sérialiseur ne doit plus être utilisé une fois le tampon libéré. Appeler cette méthode entraîne un comportement indéfini si une écriture précédente a échoué.
serializer.transferArrayBuffer(id, arrayBuffer)
id
<integer> Un entier non signé sur 32 bits.arrayBuffer
<ArrayBuffer> Une instanceArrayBuffer
.
Marque un ArrayBuffer
comme ayant son contenu transféré hors bande. Passez le ArrayBuffer
correspondant dans le contexte de désérialisation à deserializer.transferArrayBuffer()
.
serializer.writeUint32(value)
value
<integer>
Écrit un entier non signé sur 32 bits brut. À utiliser à l'intérieur d'un serializer._writeHostObject()
personnalisé.
serializer.writeUint64(hi, lo)
Écrit un entier non signé sur 64 bits brut, divisé en parties hautes et basses sur 32 bits. À utiliser à l'intérieur d'un serializer._writeHostObject()
personnalisé.
serializer.writeDouble(value)
value
<nombre>
Écrire une valeur number
JS. À utiliser à l'intérieur d'un serializer._writeHostObject()
personnalisé.
serializer.writeRawBytes(buffer)
buffer
<Buffer> | <TypedArray> | <DataView>
Écrire des octets bruts dans le tampon interne du sérialiseur. Le désérialiseur aura besoin d'un moyen de calculer la longueur du tampon. À utiliser à l'intérieur d'un serializer._writeHostObject()
personnalisé.
serializer._writeHostObject(object)
object
<Objet>
Cette méthode est appelée pour écrire un certain type d'objet hôte, c'est-à-dire un objet créé par des liaisons natives C++. S'il est impossible de sérialiser object
, une exception appropriée doit être levée.
Cette méthode n'est pas présente sur la classe Serializer
elle-même, mais peut être fournie par les sous-classes.
serializer._getDataCloneError(message)
message
<chaîne de caractères>
Cette méthode est appelée pour générer des objets d'erreur qui seront levés lorsqu'un objet ne peut pas être cloné.
Cette méthode utilise par défaut le constructeur Error
et peut être redéfinie sur les sous-classes.
serializer._getSharedArrayBufferId(sharedArrayBuffer)
sharedArrayBuffer
<SharedArrayBuffer>
Cette méthode est appelée lorsque le sérialiseur va sérialiser un objet SharedArrayBuffer
. Elle doit renvoyer un ID entier non signé sur 32 bits pour l'objet, en utilisant le même ID si ce SharedArrayBuffer
a déjà été sérialisé. Lors de la désérialisation, cet ID sera passé à deserializer.transferArrayBuffer()
.
Si l'objet ne peut pas être sérialisé, une exception doit être levée.
Cette méthode n'est pas présente sur la classe Serializer
elle-même, mais peut être fournie par les sous-classes.
serializer._setTreatArrayBufferViewsAsHostObjects(flag)
flag
<booléen> Défaut :false
Indique s'il faut traiter les objets TypedArray
et DataView
comme des objets host, c'est-à-dire les passer à serializer._writeHostObject()
.
Classe : v8.Deserializer
Ajouté dans : v8.0.0
new Deserializer(buffer)
buffer
<Buffer> | <TypedArray> | <DataView> Un buffer renvoyé parserializer.releaseBuffer()
.
Crée un nouvel objet Deserializer
.
deserializer.readHeader()
Lit et valide un en-tête (y compris la version du format). Peut, par exemple, rejeter un format filaire invalide ou non pris en charge. Dans ce cas, une erreur Error
est levée.
deserializer.readValue()
Désérialise une valeur JavaScript à partir du buffer et la renvoie.
deserializer.transferArrayBuffer(id, arrayBuffer)
id
<entier> Un entier non signé sur 32 bits.arrayBuffer
<ArrayBuffer> | <SharedArrayBuffer> Une instanceArrayBuffer
.
Marque un ArrayBuffer
comme ayant son contenu transféré hors bande. Passez le ArrayBuffer
correspondant dans le contexte de sérialisation à serializer.transferArrayBuffer()
(ou renvoyez l'id
de serializer._getSharedArrayBufferId()
dans le cas des SharedArrayBuffer
).
deserializer.getWireFormatVersion()
- Retour : <entier>
Lit la version sous-jacente du format de transmission. Principalement utile pour le code hérité lisant les anciennes versions du format de transmission. Ne doit pas être appelé avant .readHeader()
.
deserializer.readUint32()
- Retour : <entier>
Lit un entier non signé 32 bits brut et le retourne. À utiliser à l'intérieur d'un deserializer._readHostObject()
personnalisé.
deserializer.readUint64()
- Retour : <entier[]>
Lit un entier non signé 64 bits brut et le retourne sous forme de tableau [hi, lo]
avec deux entrées entières non signées 32 bits. À utiliser à l'intérieur d'un deserializer._readHostObject()
personnalisé.
deserializer.readDouble()
- Retour : <nombre>
Lit une valeur number
JS. À utiliser à l'intérieur d'un deserializer._readHostObject()
personnalisé.
deserializer.readRawBytes(length)
Lit des octets bruts à partir du tampon interne du désérialiseur. Le paramètre length
doit correspondre à la longueur du tampon qui a été passé à serializer.writeRawBytes()
. À utiliser à l'intérieur d'un deserializer._readHostObject()
personnalisé.
deserializer._readHostObject()
Cette méthode est appelée pour lire un certain type d'objet hôte, c'est-à-dire un objet créé par des liaisons natives C++. S'il n'est pas possible de désérialiser les données, une exception appropriée doit être levée.
Cette méthode n'est pas présente sur la classe Deserializer
elle-même, mais peut être fournie par les sous-classes.
Classe : v8.DefaultSerializer
Ajouté dans : v8.0.0
Sous-classe de Serializer
qui sérialise les objets TypedArray
(en particulier Buffer
) et DataView
en tant qu'objets host, et ne stocke que la partie de leurs ArrayBuffer
sous-jacents auxquels ils font référence.
Classe : v8.DefaultDeserializer
Ajouté dans : v8.0.0
Sous-classe de Deserializer
correspondant au format écrit par DefaultSerializer
.
Hooks de promesse
L'interface promiseHooks
peut être utilisée pour suivre les événements du cycle de vie des promesses. Pour suivre toute l'activité asynchrone, consultez async_hooks
qui utilise en interne ce module pour produire des événements du cycle de vie des promesses en plus des événements pour d'autres ressources asynchrones. Pour la gestion du contexte de requête, consultez AsyncLocalStorage
.
import { promiseHooks } from 'node:v8'
// Il y a quatre événements de cycle de vie produits par les promesses :
// L'événement `init` représente la création d'une promesse. Cela peut être une
// création directe comme avec `new Promise(...)` ou une continuation comme
// `then()` ou `catch()`. Cela se produit également chaque fois qu'une fonction asynchrone est
// appelée ou effectue un `await`. Si une promesse de continuation est créée, le
// `parent` sera la promesse dont elle est une continuation.
function init(promise, parent) {
console.log('une promesse a été créée', { promise, parent })
}
// L'événement `settled` se produit lorsqu'une promesse reçoit une valeur de résolution ou
// de rejet. Cela peut se produire de manière synchrone, par exemple lors de l'utilisation de
// `Promise.resolve()` sur une entrée non promise.
function settled(promise) {
console.log('une promesse résolue ou rejetée', { promise })
}
// L'événement `before` s'exécute immédiatement avant qu'un gestionnaire `then()` ou `catch()`
// s'exécute ou qu'un `await` reprenne l'exécution.
function before(promise) {
console.log('une promesse est sur le point d’appeler un gestionnaire then', { promise })
}
// L'événement `after` s'exécute immédiatement après l'exécution d'un gestionnaire `then()` ou lorsqu'un
// `await` commence après avoir repris d'un autre.
function after(promise) {
console.log('une promesse a fini d’appeler un gestionnaire then', { promise })
}
// Les hooks de cycle de vie peuvent être démarrés et arrêtés individuellement
const stopWatchingInits = promiseHooks.onInit(init)
const stopWatchingSettleds = promiseHooks.onSettled(settled)
const stopWatchingBefores = promiseHooks.onBefore(before)
const stopWatchingAfters = promiseHooks.onAfter(after)
// Ou ils peuvent être démarrés et arrêtés en groupes
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
})
// Pour arrêter un hook, appelez la fonction renvoyée lors de sa création.
stopWatchingInits()
stopWatchingSettleds()
stopWatchingBefores()
stopWatchingAfters()
stopHookSet()
promiseHooks.onInit(init)
Ajouté dans : v17.1.0, v16.14.0
init
<Function> La fonction de rappelinit
à appeler lorsqu’une promesse est créée.- Retourne : <Function> Appel pour arrêter le hook.
Le hook init
doit être une fonction simple. Fournir une fonction asynchrone générera une erreur car cela produirait une boucle infinie de microtâches.
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)
Ajouté dans : v17.1.0, v16.14.0
settled
<Function> La fonction de rappelsettled
à appeler lorsqu’une promesse est résolue ou rejetée.- Retourne : <Function> Appel pour arrêter le hook.
Le hook settled
doit être une fonction simple. Fournir une fonction asynchrone générera une erreur car cela produirait une boucle infinie de microtâches.
import { promiseHooks } from 'node:v8'
const stop = promiseHooks.onSettled(promise => {})
const { promiseHooks } = require('node:v8')
const stop = promiseHooks.onSettled(promise => {})
promiseHooks.onBefore(before)
Ajouté dans : v17.1.0, v16.14.0
before
<Function> La fonction de rappelbefore
à appeler avant l’exécution d’une continuation de promesse.- Retourne : <Function> Appel pour arrêter le hook.
Le hook before
doit être une fonction simple. Fournir une fonction asynchrone générera une erreur car cela produirait une boucle infinie de microtâches.
import { promiseHooks } from 'node:v8'
const stop = promiseHooks.onBefore(promise => {})
const { promiseHooks } = require('node:v8')
const stop = promiseHooks.onBefore(promise => {})
promiseHooks.onAfter(after)
Ajouté dans : v17.1.0, v16.14.0
after
<Function> La fonction de rappelafter
à appeler après l’exécution d’une continuation de promesse.- Retourne : <Function> Appel pour arrêter le hook.
Le hook after
doit être une fonction simple. Fournir une fonction asynchrone générera une erreur car cela produirait une boucle de microtâche infinie.
import { promiseHooks } from 'node:v8'
const stop = promiseHooks.onAfter(promise => {})
const { promiseHooks } = require('node:v8')
const stop = promiseHooks.onAfter(promise => {})
promiseHooks.createHook(callbacks)
Ajouté dans : v17.1.0, v16.14.0
callbacks
<Object> Les fonctions de rappel du hook à enregistrerinit
<Function> La fonction de rappelinit
.before
<Function> La fonction de rappelbefore
.after
<Function> La fonction de rappelafter
.settled
<Function> La fonction de rappelsettled
.
Retourne : <Function> Utilisé pour désactiver les hooks
Les fonctions de rappel du hook doivent être des fonctions simples. Fournir des fonctions asynchrones générera une erreur car cela produirait une boucle de microtâche infinie.
Enregistre les fonctions à appeler pour les différents événements de durée de vie de chaque promesse.
Les fonctions de rappel init()
/before()
/after()
/settled()
sont appelées pour les événements respectifs pendant la durée de vie d’une promesse.
Toutes les fonctions de rappel sont facultatives. Par exemple, si seul le suivi de la création de promesse est nécessaire, seule la fonction de rappel init
doit être passée. Les spécificités de toutes les fonctions pouvant être passées à callbacks
se trouvent dans la section Fonctions de rappel du 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) {},
})
Hooks de rappel
Les événements clés du cycle de vie d'une promesse ont été catégorisés en quatre zones : création d'une promesse, avant/après l'appel d'un gestionnaire de continuation ou autour d'un await
, et lorsque la promesse est résolue ou rejetée.
Bien que ces hooks soient similaires à ceux de async_hooks
, ils manquent d'un hook destroy
. Les autres types de ressources asynchrones représentent généralement des sockets ou des descripteurs de fichiers qui ont un état « fermé » distinct pour exprimer l'événement de cycle de vie destroy
, tandis que les promesses restent utilisables tant que le code peut toujours les atteindre. Le suivi de la collecte des ordures est utilisé pour faire en sorte que les promesses s'intègrent au modèle d'événement async_hooks
, cependant ce suivi est très coûteux et il se peut qu'elles ne soient même jamais collectées par le garbage collector.
Étant donné que les promesses sont des ressources asynchrones dont le cycle de vie est suivi via le mécanisme des hooks de promesse, les rappels init()
, before()
, after()
, et settled()
ne doivent pas être des fonctions asynchrones car elles créent plus de promesses ce qui produirait une boucle infinie.
Bien que cette API soit utilisée pour alimenter les événements de promesse dans async_hooks
, l'ordre entre les deux est indéfini. Les deux API sont multi-locataires et pourraient donc produire des événements dans n'importe quel ordre les unes par rapport aux autres.
init(promise, parent)
promise
<Promise> La promesse en cours de création.parent
<Promise> La promesse à partir de laquelle la continuation est effectuée, le cas échéant.
Appelée lorsqu'une promesse est construite. Cela ne signifie pas que les événements before
/after
correspondants se produiront, seulement que la possibilité existe. Cela se produira si une promesse est créée sans jamais obtenir de continuation.
before(promise)
promise
<Promise>
Appelée avant l'exécution d'une continuation de promesse. Cela peut être sous la forme de gestionnaires then()
, catch()
, ou finally()
ou d'une reprise await
.
Le rappel before
sera appelé 0 à N fois. Le rappel before
sera généralement appelé 0 fois si aucune continuation n'a jamais été effectuée pour la promesse. Le rappel before
peut être appelé plusieurs fois dans le cas où de nombreuses continuations ont été effectuées à partir de la même promesse.
after(promise)
promise
<Promise>
Appelée immédiatement après l'exécution d'une continuation de promesse. Cela peut être après un gestionnaire then()
, catch()
, ou finally()
ou avant un await
après un autre await
.
settled(promise)
promise
<Promise>
Appelée lorsque la promesse reçoit une valeur de résolution ou de rejet. Cela peut se produire de manière synchrone dans le cas de Promise.resolve()
ou Promise.reject()
.
API d'instantané de démarrage
Ajouté dans : v18.6.0, v16.17.0
[Stable : 1 - Expérimental]
Stable : 1 Stabilité : 1 - Expérimental
L'interface v8.startupSnapshot
peut être utilisée pour ajouter des hooks de sérialisation et de désérialisation pour les instantanés de démarrage personnalisés.
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# Ceci lance un processus avec l'instantané {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob
Dans l'exemple ci-dessus, entry.js
peut utiliser des méthodes de l'interface v8.startupSnapshot
pour spécifier comment enregistrer des informations pour les objets personnalisés dans l'instantané pendant la sérialisation et comment les informations peuvent être utilisées pour synchroniser ces objets pendant la désérialisation de l'instantané. Par exemple, si entry.js
contient le script suivant :
'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()
// Lecture d'une série de fichiers à partir du répertoire et stockage dans le stockage.
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 ici est l'endroit où le script d'instantané est placé
// pendant le temps de création de l'instantané.
const shelf = new BookShelf(__dirname, ['book1.en_US.txt', 'book1.es_ES.txt', 'book2.zh_CN.txt'])
assert(v8.startupSnapshot.isBuildingSnapshot())
// Lors de la sérialisation de l'instantané, comprimez les livres pour réduire la taille.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf)
// Lors de la désérialisation de l'instantané, décompressez les livres.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf)
v8.startupSnapshot.setDeserializeMainFunction(shelf => {
// process.env et process.argv sont actualisés pendant la désérialisation de l'instantané.
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)
Le binaire résultant affichera les données désérialisées à partir de l'instantané lors du démarrage, en utilisant les process.env
et process.argv
actualisés du processus lancé :
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Affiche le contenu de book1.es_ES.txt désérialisé à partir de l'instantané. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}
Actuellement, l'application désérialisée à partir d'un instantané utilisateur ne peut pas être à nouveau instantanée, donc ces API ne sont disponibles que pour les applications qui ne sont pas désérialisées à partir d'un instantané utilisateur.
v8.startupSnapshot.addSerializeCallback(callback[, data])
Ajouté dans : v18.6.0, v16.17.0
callback
<Function> Fonction de rappel à invoquer avant la sérialisation.data
<any> Données optionnelles qui seront passées à la fonctioncallback
lorsqu'elle sera appelée.
Ajoute une fonction de rappel qui sera appelée lorsque l'instance Node.js est sur le point d'être sérialisée dans un snapshot et de se terminer. Cela peut être utilisé pour libérer des ressources qui ne doivent pas ou ne peuvent pas être sérialisées, ou pour convertir des données utilisateur dans une forme plus adaptée à la sérialisation.
Les fonctions de rappel sont exécutées dans l'ordre dans lequel elles sont ajoutées.
v8.startupSnapshot.addDeserializeCallback(callback[, data])
Ajouté dans : v18.6.0, v16.17.0
callback
<Function> Fonction de rappel à invoquer après la désérialisation du snapshot.data
<any> Données optionnelles qui seront passées à la fonctioncallback
lorsqu'elle sera appelée.
Ajoute une fonction de rappel qui sera appelée lorsque l'instance Node.js est désérialisée à partir d'un snapshot. La fonction callback
et les données data
(si fournies) seront sérialisées dans le snapshot ; elles peuvent être utilisées pour réinitialiser l'état de l'application ou pour acquérir à nouveau les ressources dont l'application a besoin lorsque l'application est redémarrée à partir du snapshot.
Les fonctions de rappel sont exécutées dans l'ordre dans lequel elles sont ajoutées.
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])
Ajouté dans : v18.6.0, v16.17.0
callback
<Function> Fonction de rappel à invoquer comme point d'entrée après la désérialisation du snapshot.data
<any> Données optionnelles qui seront passées à la fonctioncallback
lorsqu'elle sera appelée.
Cela définit le point d'entrée de l'application Node.js lorsqu'elle est désérialisée à partir d'un snapshot. Cela ne peut être appelé qu'une seule fois dans le script de création du snapshot. Si appelé, l'application désérialisée n'a plus besoin d'un script de point d'entrée supplémentaire pour démarrer et invoquera simplement la fonction de rappel avec les données désérialisées (si fournies), sinon un script de point d'entrée doit toujours être fourni à l'application désérialisée.
v8.startupSnapshot.isBuildingSnapshot()
Ajouté dans : v18.6.0, v16.17.0
- Retourne : <boolean>
Retourne true
si l'instance Node.js est exécutée pour construire un snapshot.
Classe : v8.GCProfiler
Ajouté dans : v19.6.0, v18.15.0
Cette API collecte les données GC dans le thread courant.
new v8.GCProfiler()
Ajouté dans : v19.6.0, v18.15.0
Crée une nouvelle instance de la classe v8.GCProfiler
.
profiler.start()
Ajouté dans : v19.6.0, v18.15.0
Commence la collecte des données GC.
profiler.stop()
Ajouté dans : v19.6.0, v18.15.0
Arrête la collecte des données GC et retourne un objet. Le contenu de l'objet est le suivant :
{
"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
}
Voici un exemple.
const { GCProfiler } = require('node:v8')
const profiler = new GCProfiler()
profiler.start()
setTimeout(() => {
console.log(profiler.stop())
}, 1000)