Skip to content

V8

Quellcode: lib/v8.js

Das Modul node:v8 stellt APIs zur Verfügung, die spezifisch für die Version von V8 sind, die in die Node.js-Binärdatei eingebaut ist. Der Zugriff erfolgt über:

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

v8.cachedDataVersionTag()

Hinzugefügt in: v8.0.0

Gibt eine Ganzzahl zurück, die ein Versions-Tag darstellt, das von der V8-Version, den Befehlszeilen-Flags und den erkannten CPU-Funktionen abgeleitet wurde. Dies ist nützlich, um festzustellen, ob ein cachedData-Puffer von vm.Script mit dieser Instanz von V8 kompatibel ist.

js
console.log(v8.cachedDataVersionTag()) // 3947234607
// Der von v8.cachedDataVersionTag() zurückgegebene Wert wird von der V8-Version,
// den Befehlszeilen-Flags und den erkannten CPU-Funktionen abgeleitet. Testen Sie,
// ob sich der Wert tatsächlich ändert, wenn Flags umgeschaltet werden.
v8.setFlagsFromString('--allow_natives_syntax')
console.log(v8.cachedDataVersionTag()) // 183726201

v8.getHeapCodeStatistics()

Hinzugefügt in: v12.8.0

Ruft Statistiken über Code und dessen Metadaten im Heap ab, siehe V8 GetHeapCodeAndMetadataStatistics API. Gibt ein Objekt mit den folgenden Eigenschaften zurück:

js
{
  code_and_metadata_size: 212208,
  bytecode_and_metadata_size: 161368,
  external_script_source_size: 1410794,
  cpu_profiler_metadata_size: 0,
}

v8.getHeapSnapshot([options])

[Historie]

VersionÄnderungen
v19.1.0Unterstützung für Optionen zur Konfiguration des Heap-Snapshots.
v11.13.0Hinzugefügt in: v11.13.0
  • options <Object>

    • exposeInternals <boolean> Wenn true, werden Internals im Heap-Snapshot exponiert. Standard: false.
    • exposeNumericValues <boolean> Wenn true, werden numerische Werte in künstlichen Feldern exponiert. Standard: false.
  • Gibt zurück: <stream.Readable> Ein Readable, das den V8-Heap-Snapshot enthält.

Generiert einen Snapshot des aktuellen V8-Heaps und gibt einen Readable Stream zurück, der verwendet werden kann, um die JSON-serialisierte Darstellung zu lesen. Dieses JSON-Stream-Format ist für die Verwendung mit Tools wie Chrome DevTools vorgesehen. Das JSON-Schema ist undokumentiert und spezifisch für die V8-Engine. Daher kann sich das Schema von einer V8-Version zur nächsten ändern.

Das Erstellen eines Heap-Snapshots erfordert etwa die doppelte Speichermenge wie der Heap zum Zeitpunkt der Erstellung des Snapshots. Dies birgt das Risiko, dass OOM-Killer den Prozess beenden.

Das Generieren eines Snapshots ist eine synchrone Operation, die die Event-Loop für eine Dauer blockiert, die von der Heap-Größe abhängt.

js
// Heap-Snapshot in der Konsole ausgeben
const v8 = require('node:v8')
const stream = v8.getHeapSnapshot()
stream.pipe(process.stdout)

v8.getHeapSpaceStatistics()

[Historie]

VersionÄnderungen
v7.5.0Unterstützung für Werte, die den 32-Bit-Ganzzahlbereich ohne Vorzeichen überschreiten.
v6.0.0Hinzugefügt in: v6.0.0

Gibt Statistiken über die V8-Heap-Bereiche zurück, d. h. die Segmente, aus denen der V8-Heap besteht. Weder die Reihenfolge der Heap-Bereiche noch die Verfügbarkeit eines Heap-Bereichs können garantiert werden, da die Statistiken über die V8 GetHeapSpaceStatistics-Funktion bereitgestellt werden und sich von einer V8-Version zur nächsten ändern können.

Der zurückgegebene Wert ist ein Array von Objekten mit den folgenden Eigenschaften:

json
[
  {
    "space_name": "new_space",
    "space_size": 2063872,
    "space_used_size": 951112,
    "space_available_size": 80824,
    "physical_space_size": 2063872
  },
  {
    "space_name": "old_space",
    "space_size": 3090560,
    "space_used_size": 2493792,
    "space_available_size": 0,
    "physical_space_size": 3090560
  },
  {
    "space_name": "code_space",
    "space_size": 1260160,
    "space_used_size": 644256,
    "space_available_size": 960,
    "physical_space_size": 1260160
  },
  {
    "space_name": "map_space",
    "space_size": 1094160,
    "space_used_size": 201608,
    "space_available_size": 0,
    "physical_space_size": 1094160
  },
  {
    "space_name": "large_object_space",
    "space_size": 0,
    "space_used_size": 0,
    "space_available_size": 1490980608,
    "physical_space_size": 0
  }
]

v8.getHeapStatistics()

[Historie]

VersionÄnderungen
v7.5.0Unterstützt Werte, die den 32-Bit-Ganzzahlbereich ohne Vorzeichen überschreiten.
v7.2.0malloced_memory, peak_malloced_memory und does_zap_garbage hinzugefügt.
v1.0.0Hinzugefügt in: v1.0.0

Gibt ein Objekt mit den folgenden Eigenschaften zurück:

total_heap_size Der Wert von total_heap_size ist die Anzahl der Bytes, die V8 für den Heap zugewiesen hat. Dieser Wert kann anwachsen, wenn used_heap mehr Speicher benötigt.

total_heap_size_executable Der Wert von total_heap_size_executable ist der Teil des Heaps, der ausführbaren Code enthalten kann, in Bytes. Dies beinhaltet Speicher, der von JIT-kompiliertem Code verwendet wird, und jeglichen Speicher, der ausführbar gehalten werden muss.

total_physical_size Der Wert von total_physical_size ist der tatsächliche physikalische Speicher, der vom V8-Heap verwendet wird, in Bytes. Dies ist die Speichermenge, die zugewiesen (oder verwendet) wird, anstatt reserviert zu sein.

total_available_size Der Wert von total_available_size ist die Anzahl der Bytes an Speicher, die dem V8-Heap zur Verfügung stehen. Dieser Wert stellt dar, wie viel mehr Speicher V8 verwenden kann, bevor er das Heap-Limit überschreitet.

used_heap_size Der Wert von used_heap_size ist die Anzahl der Bytes, die derzeit von V8-JavaScript-Objekten verwendet werden. Dies ist der tatsächlich verwendete Speicher und beinhaltet keinen Speicher, der zugewiesen, aber noch nicht verwendet wurde.

heap_size_limit Der Wert von heap_size_limit ist die maximale Größe des V8-Heaps in Bytes (entweder das Standardlimit, das durch Systemressourcen bestimmt wird, oder der Wert, der an die Option --max_old_space_size übergeben wurde).

malloced_memory Der Wert von malloced_memory ist die Anzahl der Bytes, die von V8 durch malloc zugewiesen wurden.

peak_malloced_memory Der Wert von peak_malloced_memory ist die maximale Anzahl der Bytes, die während der Lebensdauer des Prozesses durch malloc von V8 zugewiesen wurden.

does_zap_garbage ist ein boolescher Wert 0/1, der angibt, ob die Option --zap_code_space aktiviert ist oder nicht. Dies bewirkt, dass V8 Heap-Garbage mit einem Bitmuster überschreibt. Der RSS-Footprint (Resident Set Size) wird größer, da er kontinuierlich alle Heap-Seiten berührt, was es unwahrscheinlicher macht, dass sie vom Betriebssystem ausgelagert werden.

number_of_native_contexts Der Wert von native_context ist die Anzahl der aktuell aktiven Top-Level-Kontexte. Die Zunahme dieser Zahl im Laufe der Zeit deutet auf ein Speicherleck hin.

number_of_detached_contexts Der Wert von detached_context ist die Anzahl der Kontexte, die abgetrennt und noch nicht per Garbage Collection entfernt wurden. Wenn diese Zahl ungleich Null ist, deutet dies auf ein mögliches Speicherleck hin.

total_global_handles_size Der Wert von total_global_handles_size ist die gesamte Speichergröße von V8 globalen Handles.

used_global_handles_size Der Wert von used_global_handles_size ist die verwendete Speichergröße von V8 globalen Handles.

external_memory Der Wert von external_memory ist die Speichergröße von Array-Puffern und externen Strings.

js
{
  total_heap_size: 7326976,
  total_heap_size_executable: 4194304,
  total_physical_size: 7326976,
  total_available_size: 1152656,
  used_heap_size: 3476208,
  heap_size_limit: 1535115264,
  malloced_memory: 16384,
  peak_malloced_memory: 1127496,
  does_zap_garbage: 0,
  number_of_native_contexts: 1,
  number_of_detached_contexts: 0,
  total_global_handles_size: 8192,
  used_global_handles_size: 3296,
  external_memory: 318824
}

v8.queryObjects(ctor[, options])

Hinzugefügt in: v22.0.0, v20.13.0

[Stabil: 1 - Experimentell]

Stabil: 1 Stabilität: 1.1 - Aktive Entwicklung

  • ctor <Function> Der Konstruktor, der verwendet werden kann, um in der Prototypen-Kette zu suchen, um Zielobjekte im Heap zu filtern.

  • options <undefined> | <Object>

    • format <string> Wenn es 'count' ist, wird die Anzahl der gefundenen Objekte zurückgegeben. Wenn es 'summary' ist, wird ein Array mit Zusammenfassungs-Strings der gefundenen Objekte zurückgegeben.
  • Gibt zurück: {number|Array

Dies ähnelt der queryObjects() Console-API, die von der Chromium DevTools-Konsole bereitgestellt wird. Sie kann verwendet werden, um nach Objekten zu suchen, die den übereinstimmenden Konstruktor in ihrer Prototypenkette im Heap nach einer vollständigen Garbage Collection haben, was für Regressionstests von Speicherlecks nützlich sein kann. Um überraschende Ergebnisse zu vermeiden, sollten Benutzer diese API nicht für Konstruktoren verwenden, deren Implementierung sie nicht kontrollieren, oder für Konstruktoren, die von anderen Parteien in der Anwendung aufgerufen werden können.

Um versehentliche Lecks zu vermeiden, gibt diese API keine Rohverweise auf die gefundenen Objekte zurück. Standardmäßig wird die Anzahl der gefundenen Objekte zurückgegeben. Wenn options.format 'summary' ist, wird ein Array zurückgegeben, das kurze String-Darstellungen für jedes Objekt enthält. Die in dieser API bereitgestellte Sichtbarkeit ähnelt der, die der Heap-Snapshot bietet, während Benutzer die Kosten für die Serialisierung und das Parsing sparen und die Zielobjekte direkt während der Suche filtern können.

Nur Objekte, die im aktuellen Ausführungskontext erstellt wurden, sind in den Ergebnissen enthalten.

js
const { queryObjects } = require('node:v8')
class A {
  foo = 'bar'
}
console.log(queryObjects(A)) // 0
const a = new A()
console.log(queryObjects(A)) // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

class B extends A {
  bar = 'qux'
}
const b = new B()
console.log(queryObjects(B)) // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }))

// Beachten Sie, dass, wenn es Kindklassen gibt, die von einem Konstruktor erben,
// der Konstruktor auch in der Prototypenkette des Prototyps der Kindklasse
// auftaucht, sodass der Prototyp der Kindklasse auch im Ergebnis
// enthalten ist.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))
js
import { queryObjects } from 'node:v8'
class A {
  foo = 'bar'
}
console.log(queryObjects(A)) // 0
const a = new A()
console.log(queryObjects(A)) // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

class B extends A {
  bar = 'qux'
}
const b = new B()
console.log(queryObjects(B)) // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }))

// Beachten Sie, dass, wenn es Kindklassen gibt, die von einem Konstruktor erben,
// der Konstruktor auch in der Prototypenkette des Prototyps der Kindklasse
// auftaucht, sodass der Prototyp der Kindklasse auch im Ergebnis
// enthalten ist.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

v8.setFlagsFromString(flags)

Hinzugefügt in: v1.0.0

Die Methode v8.setFlagsFromString() kann verwendet werden, um V8-Befehlszeilen-Flags programmgesteuert zu setzen. Diese Methode sollte mit Vorsicht verwendet werden. Das Ändern von Einstellungen nach dem Starten der VM kann zu unvorhersehbarem Verhalten führen, einschließlich Abstürzen und Datenverlust; oder es kann einfach nichts bewirken.

Die für eine Node.js-Version verfügbaren V8-Optionen können durch Ausführen von node --v8-options ermittelt werden.

Verwendung:

js
// GC-Ereignisse eine Minute lang auf stdout ausgeben.
const v8 = require('node:v8')
v8.setFlagsFromString('--trace_gc')
setTimeout(() => {
  v8.setFlagsFromString('--notrace_gc')
}, 60e3)

v8.stopCoverage()

Hinzugefügt in: v15.1.0, v14.18.0, v12.22.0

Die Methode v8.stopCoverage() ermöglicht es dem Benutzer, die von NODE_V8_COVERAGE gestartete Abdeckungserfassung zu stoppen, sodass V8 die Ausführungszählungsdatensätze freigeben und Code optimieren kann. Dies kann in Verbindung mit v8.takeCoverage() verwendet werden, wenn der Benutzer die Abdeckung bei Bedarf erfassen möchte.

v8.takeCoverage()

Hinzugefügt in: v15.1.0, v14.18.0, v12.22.0

Die Methode v8.takeCoverage() ermöglicht es dem Benutzer, die von NODE_V8_COVERAGE gestartete Abdeckung bei Bedarf auf die Festplatte zu schreiben. Diese Methode kann während der Lebensdauer des Prozesses mehrfach aufgerufen werden. Jedes Mal wird der Ausführungszähler zurückgesetzt und ein neuer Abdeckungsbericht in das von NODE_V8_COVERAGE angegebene Verzeichnis geschrieben.

Wenn der Prozess kurz vor dem Beenden steht, wird noch eine letzte Abdeckung auf die Festplatte geschrieben, es sei denn, v8.stopCoverage() wird vor dem Beenden des Prozesses aufgerufen.

v8.writeHeapSnapshot([filename[,options]])

[Verlauf]

VersionÄnderungen
v19.1.0Unterstützung von Optionen zur Konfiguration des Heap-Snapshots.
v18.0.0Es wird nun eine Ausnahme ausgelöst, wenn die Datei nicht geschrieben werden konnte.
v18.0.0Die zurückgegebenen Fehlercodes werden über alle Plattformen hinweg konsistent gemacht.
v11.13.0Hinzugefügt in: v11.13.0
  • filename <string> Der Dateipfad, in dem der V8-Heap-Snapshot gespeichert werden soll. Wenn nicht angegeben, wird ein Dateiname mit dem Muster 'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot' generiert, wobei {pid} die PID des Node.js-Prozesses ist, {thread_id} ist 0, wenn writeHeapSnapshot() vom Haupt-Node.js-Thread aufgerufen wird, oder die ID eines Worker-Threads.

  • options <Object>

    • exposeInternals <boolean> Wenn true, werden interne Elemente im Heap-Snapshot freigelegt. Standard: false.
    • exposeNumericValues <boolean> Wenn true, werden numerische Werte in künstlichen Feldern freigelegt. Standard: false.
  • Gibt zurück: <string> Der Dateiname, unter dem der Snapshot gespeichert wurde.

Generiert einen Snapshot des aktuellen V8-Heaps und schreibt ihn in eine JSON-Datei. Diese Datei ist für die Verwendung mit Tools wie Chrome DevTools gedacht. Das JSON-Schema ist nicht dokumentiert und spezifisch für die V8-Engine und kann sich von einer V8-Version zur nächsten ändern.

Ein Heap-Snapshot ist spezifisch für ein einzelnes V8-Isolat. Bei Verwendung von Worker-Threads enthält ein vom Haupt-Thread generierter Heap-Snapshot keine Informationen über die Worker und umgekehrt.

Das Erstellen eines Heap-Snapshots erfordert etwa die doppelte Speichermenge des Heaps zum Zeitpunkt der Erstellung des Snapshots. Dies führt zu dem Risiko, dass OOM-Killer den Prozess beenden.

Das Generieren eines Snapshots ist ein synchroner Vorgang, der die Ereignisschleife für eine Dauer blockiert, die von der Heap-Größe abhängt.

js
const { writeHeapSnapshot } = require('node:v8')
const { Worker, isMainThread, parentPort } = require('node:worker_threads')

if (isMainThread) {
  const worker = new Worker(__filename)

  worker.once('message', filename => {
    console.log(`worker heapdump: ${filename}`)
    // Jetzt einen Heapdump für den Haupt-Thread holen.
    console.log(`main thread heapdump: ${writeHeapSnapshot()}`)
  })

  // Den Worker anweisen, einen Heapdump zu erstellen.
  worker.postMessage('heapdump')
} else {
  parentPort.once('message', message => {
    if (message === 'heapdump') {
      // Generiere einen Heapdump für den Worker
      // und gebe den Dateinamen an den Elternteil zurück.
      parentPort.postMessage(writeHeapSnapshot())
    }
  })
}

v8.setHeapSnapshotNearHeapLimit(limit)

Hinzugefügt in: v18.10.0, v16.18.0

[Stabil: 1 - Experimentell]

Stabil: 1 Stabilität: 1 - Experimentell

Die API ist eine Nulloperation, wenn --heapsnapshot-near-heap-limit bereits über die Kommandozeile festgelegt wurde oder die API mehr als einmal aufgerufen wird. limit muss eine positive Ganzzahl sein. Siehe --heapsnapshot-near-heap-limit für weitere Informationen.

Serialisierungs-API

Die Serialisierungs-API bietet Mittel zum Serialisieren von JavaScript-Werten auf eine Weise, die mit dem HTML-Strukturierungs-Klon-Algorithmus kompatibel ist.

Das Format ist abwärtskompatibel (d.h. sicher auf der Festplatte zu speichern). Gleiche JavaScript-Werte können zu unterschiedlicher serialisierter Ausgabe führen.

v8.serialize(value)

Hinzugefügt in: v8.0.0

Verwendet einen DefaultSerializer, um value in einen Puffer zu serialisieren.

ERR_BUFFER_TOO_LARGE wird ausgelöst, wenn versucht wird, ein riesiges Objekt zu serialisieren, das einen Puffer benötigt, der größer ist als buffer.constants.MAX_LENGTH.

v8.deserialize(buffer)

Hinzugefügt in: v8.0.0

Verwendet einen DefaultDeserializer mit Standardoptionen, um einen JS-Wert aus einem Puffer zu lesen.

Klasse: v8.Serializer

Hinzugefügt in: v8.0.0

new Serializer()

Erstellt ein neues Serializer-Objekt.

serializer.writeHeader()

Schreibt einen Header, der die Version des Serialisierungsformats enthält.

serializer.writeValue(value)

Serialisiert einen JavaScript-Wert und fügt die serialisierte Darstellung dem internen Puffer hinzu.

Dies wirft einen Fehler, wenn value nicht serialisiert werden kann.

serializer.releaseBuffer()

Gibt den gespeicherten internen Puffer zurück. Dieser Serialisierer sollte nicht mehr verwendet werden, sobald der Puffer freigegeben wurde. Das Aufrufen dieser Methode führt zu undefiniertem Verhalten, wenn ein vorheriger Schreibvorgang fehlgeschlagen ist.

serializer.transferArrayBuffer(id, arrayBuffer)

Markiert ein ArrayBuffer als außerhalb des Bandes übertragene Inhalte. Übergeben Sie das entsprechende ArrayBuffer im Deserialisierungskontext an deserializer.transferArrayBuffer().

serializer.writeUint32(value)

Schreibt eine rohe 32-Bit-Ganzzahl ohne Vorzeichen. Zur Verwendung innerhalb eines benutzerdefinierten serializer._writeHostObject().

serializer.writeUint64(hi, lo)

Schreibt eine rohe 64-Bit-Ganzzahl ohne Vorzeichen, aufgeteilt in hohe und niedrige 32-Bit-Teile. Zur Verwendung innerhalb eines benutzerdefinierten serializer._writeHostObject().

serializer.writeDouble(value)

Schreibt einen JS number-Wert. Zur Verwendung innerhalb einer benutzerdefinierten serializer._writeHostObject().

serializer.writeRawBytes(buffer)

Schreibt rohe Bytes in den internen Puffer des Serialisierers. Der Deserialisierer benötigt eine Möglichkeit, die Länge des Puffers zu berechnen. Zur Verwendung innerhalb einer benutzerdefinierten serializer._writeHostObject().

serializer._writeHostObject(object)

Diese Methode wird aufgerufen, um eine Art Host-Objekt zu schreiben, d.h. ein Objekt, das durch native C++-Bindings erstellt wurde. Wenn es nicht möglich ist, object zu serialisieren, sollte eine geeignete Ausnahme ausgelöst werden.

Diese Methode ist nicht in der Serializer-Klasse selbst vorhanden, kann aber von Unterklassen bereitgestellt werden.

serializer._getDataCloneError(message)

Diese Methode wird aufgerufen, um Fehlerobjekte zu generieren, die ausgelöst werden, wenn ein Objekt nicht geklont werden kann.

Diese Methode verwendet standardmäßig den Error Konstruktor und kann in Unterklassen überschrieben werden.

serializer._getSharedArrayBufferId(sharedArrayBuffer)

Diese Methode wird aufgerufen, wenn der Serialisierer ein SharedArrayBuffer-Objekt serialisieren wird. Sie muss eine vorzeichenlose 32-Bit-Ganzzahl-ID für das Objekt zurückgeben, wobei dieselbe ID verwendet wird, wenn dieses SharedArrayBuffer bereits serialisiert wurde. Beim Deserialisieren wird diese ID an deserializer.transferArrayBuffer() übergeben.

Wenn das Objekt nicht serialisiert werden kann, sollte eine Ausnahme ausgelöst werden.

Diese Methode ist nicht in der Serializer-Klasse selbst vorhanden, kann aber von Unterklassen bereitgestellt werden.

serializer._setTreatArrayBufferViewsAsHostObjects(flag)

Gibt an, ob TypedArray- und DataView-Objekte als Hostobjekte behandelt werden sollen, d. h. sie an serializer._writeHostObject() übergeben werden sollen.

Klasse: v8.Deserializer

Hinzugefügt in: v8.0.0

new Deserializer(buffer)

Erstellt ein neues Deserializer-Objekt.

deserializer.readHeader()

Liest und validiert einen Header (einschließlich der Formatversion). Kann beispielsweise ein ungültiges oder nicht unterstütztes Wire-Format ablehnen. In diesem Fall wird ein Error ausgelöst.

deserializer.readValue()

Deserialisiert einen JavaScript-Wert aus dem Puffer und gibt ihn zurück.

deserializer.transferArrayBuffer(id, arrayBuffer)

Markiert einen ArrayBuffer als außerhalb des Bandes übertragen. Übergeben Sie den entsprechenden ArrayBuffer im Serialisierungskontext an serializer.transferArrayBuffer() (oder geben Sie die id von serializer._getSharedArrayBufferId() im Fall von SharedArrayBuffers zurück).

deserializer.getWireFormatVersion()

Liest die zugrunde liegende Wire-Format-Version. Wahrscheinlich hauptsächlich für Legacy-Code nützlich, der alte Wire-Format-Versionen liest. Darf nicht vor .readHeader() aufgerufen werden.

deserializer.readUint32()

Liest eine rohe 32-Bit-Ganzzahl ohne Vorzeichen und gibt sie zurück. Zur Verwendung innerhalb eines benutzerdefinierten deserializer._readHostObject().

deserializer.readUint64()

Liest eine rohe 64-Bit-Ganzzahl ohne Vorzeichen und gibt sie als Array [hi, lo] mit zwei 32-Bit-Ganzzahleinträgen ohne Vorzeichen zurück. Zur Verwendung innerhalb eines benutzerdefinierten deserializer._readHostObject().

deserializer.readDouble()

Liest einen JS number-Wert. Zur Verwendung innerhalb eines benutzerdefinierten deserializer._readHostObject().

deserializer.readRawBytes(length)

Liest rohe Bytes aus dem internen Puffer des Deserialisierers. Der Parameter length muss der Länge des Puffers entsprechen, der an serializer.writeRawBytes() übergeben wurde. Zur Verwendung innerhalb eines benutzerdefinierten deserializer._readHostObject().

deserializer._readHostObject()

Diese Methode wird aufgerufen, um eine Art Host-Objekt zu lesen, d. h. ein Objekt, das von nativen C++-Bindings erstellt wurde. Wenn es nicht möglich ist, die Daten zu deserialisieren, sollte eine geeignete Ausnahme ausgelöst werden.

Diese Methode ist nicht in der Deserializer-Klasse selbst vorhanden, kann aber von Unterklassen bereitgestellt werden.

Klasse: v8.DefaultSerializer

Hinzugefügt in: v8.0.0

Eine Unterklasse von Serializer, die TypedArray- (insbesondere Buffer) und DataView-Objekte als Host-Objekte serialisiert und nur den Teil ihrer zugrunde liegenden ArrayBuffer speichert, auf den sie verweisen.

Klasse: v8.DefaultDeserializer

Hinzugefügt in: v8.0.0

Eine Unterklasse von Deserializer, die dem Format entspricht, das von DefaultSerializer geschrieben wurde.

Promise-Hooks

Die promiseHooks-Schnittstelle kann verwendet werden, um Promise-Lifecycle-Ereignisse zu verfolgen. Um alle asynchronen Aktivitäten zu verfolgen, siehe async_hooks, das intern dieses Modul verwendet, um Promise-Lifecycle-Ereignisse zusätzlich zu Ereignissen für andere asynchrone Ressourcen zu erzeugen. Informationen zur Verwaltung von Anforderungskontexten finden Sie unter AsyncLocalStorage.

js
import { promiseHooks } from 'node:v8'

// Es gibt vier Lifecycle-Ereignisse, die von Promises erzeugt werden:

// Das `init`-Ereignis stellt die Erstellung eines Promise dar. Dies kann eine
// direkte Erstellung sein, wie bei `new Promise(...)`, oder eine Fortsetzung
// wie bei `then()` oder `catch()`. Es tritt auch auf, wenn eine asynchrone Funktion
// aufgerufen wird oder ein `await` ausführt. Wenn ein Fortsetzungspromise erstellt
// wird, ist `parent` das Promise, von dem es eine Fortsetzung ist.
function init(promise, parent) {
  console.log('ein Promise wurde erstellt', { promise, parent })
}

// Das `settled`-Ereignis tritt auf, wenn ein Promise einen Auflösungs- oder
// Ablehnungswert empfängt. Dies kann synchron geschehen, wie z. B. bei der Verwendung
// von `Promise.resolve()` für Nicht-Promise-Eingaben.
function settled(promise) {
  console.log('ein Promise wurde aufgelöst oder abgelehnt', { promise })
}

// Das `before`-Ereignis wird unmittelbar vor dem Ausführen eines `then()`- oder
// `catch()`-Handlers oder dem Fortsetzen der Ausführung durch ein `await` ausgeführt.
function before(promise) {
  console.log('ein Promise ist im Begriff, einen then-Handler aufzurufen', { promise })
}

// Das `after`-Ereignis wird unmittelbar nach dem Ausführen eines `then()`-Handlers
// oder beim Starten eines `await` nach der Wiederaufnahme von einem anderen ausgeführt.
function after(promise) {
  console.log('ein Promise hat das Aufrufen eines then-Handlers beendet', { promise })
}

// Lifecycle-Hooks können einzeln gestartet und gestoppt werden
const stopWatchingInits = promiseHooks.onInit(init)
const stopWatchingSettleds = promiseHooks.onSettled(settled)
const stopWatchingBefores = promiseHooks.onBefore(before)
const stopWatchingAfters = promiseHooks.onAfter(after)

// Oder sie können in Gruppen gestartet und gestoppt werden
const stopHookSet = promiseHooks.createHook({
  init,
  settled,
  before,
  after,
})

// Um einen Hook zu stoppen, rufen Sie die Funktion auf, die bei seiner Erstellung zurückgegeben wurde.
stopWatchingInits()
stopWatchingSettleds()
stopWatchingBefores()
stopWatchingAfters()
stopHookSet()

promiseHooks.onInit(init)

Hinzugefügt in: v17.1.0, v16.14.0

Der init-Hook muss eine einfache Funktion sein. Die Bereitstellung einer Async-Funktion führt zu einem Fehler, da dies zu einer unendlichen Mikrotask-Schleife führen würde.

js
import { promiseHooks } from 'node:v8'

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

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

promiseHooks.onSettled(settled)

Hinzugefügt in: v17.1.0, v16.14.0

Der settled-Hook muss eine einfache Funktion sein. Die Bereitstellung einer Async-Funktion führt zu einem Fehler, da dies zu einer unendlichen Mikrotask-Schleife führen würde.

js
import { promiseHooks } from 'node:v8'

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

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

promiseHooks.onBefore(before)

Hinzugefügt in: v17.1.0, v16.14.0

Der before-Hook muss eine einfache Funktion sein. Die Bereitstellung einer Async-Funktion führt zu einem Fehler, da dies zu einer unendlichen Mikrotask-Schleife führen würde.

js
import { promiseHooks } from 'node:v8'

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

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

promiseHooks.onAfter(after)

Hinzugefügt in: v17.1.0, v16.14.0

Der after-Hook muss eine einfache Funktion sein. Die Bereitstellung einer asynchronen Funktion löst einen Fehler aus, da dies zu einer unendlichen Microtask-Schleife führen würde.

js
import { promiseHooks } from 'node:v8'

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

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

promiseHooks.createHook(callbacks)

Hinzugefügt in: v17.1.0, v16.14.0

Die Hook-Callbacks müssen einfache Funktionen sein. Die Bereitstellung asynchroner Funktionen löst einen Fehler aus, da dies zu einer unendlichen Microtask-Schleife führen würde.

Registriert Funktionen, die für verschiedene Lebensdauerereignisse jedes Promise aufgerufen werden sollen.

Die Callbacks init()/before()/after()/settled() werden für die jeweiligen Ereignisse während der Lebensdauer eines Promises aufgerufen.

Alle Callbacks sind optional. Wenn beispielsweise nur die Promise-Erstellung verfolgt werden muss, muss nur der init-Callback übergeben werden. Die Besonderheiten aller Funktionen, die an callbacks übergeben werden können, finden Sie im Abschnitt Hook-Callbacks.

js
import { promiseHooks } from 'node:v8'

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

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

Hook-Rückrufe

Schlüsselereignisse im Lebenszyklus einer Promise wurden in vier Bereiche kategorisiert: Erstellung einer Promise, vor/nach dem Aufruf eines Fortsetzungs-Handlers oder um ein Await herum, und wenn die Promise aufgelöst oder abgelehnt wird.

Obwohl diese Hooks denen von async_hooks ähneln, fehlt ihnen ein destroy-Hook. Andere Arten von asynchronen Ressourcen repräsentieren typischerweise Sockets oder Dateideskriptoren, die einen deutlichen "geschlossenen" Zustand haben, um das destroy-Lebenszyklusereignis auszudrücken, während Promises so lange verwendbar bleiben, wie Code sie noch erreichen kann. Die Garbage Collection-Verfolgung wird verwendet, um Promises in das async_hooks-Ereignismodell einzupassen, aber diese Verfolgung ist sehr aufwendig und sie werden möglicherweise nie von der Garbage Collection erfasst.

Da Promises asynchrone Ressourcen sind, deren Lebenszyklus über den Promise-Hooks-Mechanismus verfolgt wird, dürfen die init(), before(), after() und settled()-Rückrufe keine asynchronen Funktionen sein, da sie weitere Promises erzeugen würden, die eine Endlosschleife verursachen würden.

Während diese API verwendet wird, um Promise-Ereignisse in async_hooks einzuspeisen, ist die Reihenfolge zwischen den beiden undefiniert. Beide APIs sind mandantenfähig und könnten daher Ereignisse in beliebiger Reihenfolge zueinander erzeugen.

init(promise, parent)

  • promise <Promise> Die Promise, die gerade erstellt wird.
  • parent <Promise> Die Promise, von der fortgesetzt wurde, falls zutreffend.

Wird aufgerufen, wenn eine Promise erstellt wird. Dies bedeutet nicht, dass entsprechende before/after-Ereignisse auftreten werden, sondern nur, dass die Möglichkeit besteht. Dies geschieht, wenn eine Promise erstellt wird, ohne dass jemals eine Fortsetzung erfolgt.

before(promise)

Wird aufgerufen, bevor eine Promise-Fortsetzung ausgeführt wird. Dies kann in Form von then(), catch() oder finally()-Handlern oder einem await erfolgen, das fortgesetzt wird.

Der before-Rückruf wird 0 bis N Mal aufgerufen. Der before-Rückruf wird typischerweise 0 Mal aufgerufen, wenn nie eine Fortsetzung für die Promise gemacht wurde. Der before-Rückruf kann mehrmals aufgerufen werden, wenn viele Fortsetzungen aus derselben Promise gemacht wurden.

after(promise)

Wird unmittelbar nach der Ausführung einer Promise-Fortsetzung aufgerufen. Dies kann nach einem then(), catch() oder finally()-Handler oder vor einem await nach einem anderen await der Fall sein.

settled(promise)

Wird aufgerufen, wenn die Promise einen Auflösungs- oder Ablehnungswert erhält. Dies kann im Fall von Promise.resolve() oder Promise.reject() synchron auftreten.

Startup Snapshot API

Hinzugefügt in: v18.6.0, v16.17.0

[Stabil: 1 - Experimentell]

Stabil: 1 Stabilität: 1 - Experimentell

Die v8.startupSnapshot-Schnittstelle kann verwendet werden, um Serialisierungs- und Deserialisierungshooks für benutzerdefinierte Startup-Snapshots hinzuzufügen.

bash
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# Dies startet einen Prozess mit dem Snapshot {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob

Im obigen Beispiel kann entry.js Methoden der v8.startupSnapshot-Schnittstelle verwenden, um anzugeben, wie Informationen für benutzerdefinierte Objekte im Snapshot während der Serialisierung gespeichert werden und wie die Informationen verwendet werden können, um diese Objekte während der Deserialisierung des Snapshots zu synchronisieren. Wenn die entry.js beispielsweise das folgende Skript enthält:

js
'use strict'

const fs = require('node:fs')
const zlib = require('node:zlib')
const path = require('node:path')
const assert = require('node:assert')

const v8 = require('node:v8')

class BookShelf {
  storage = new Map()

  // Lesen einer Reihe von Dateien aus dem Verzeichnis und Speichern 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 ist hier der Ort, an dem das Snapshot-Skript
// während der Snapshot-Erstellungszeit platziert wird.
const shelf = new BookShelf(__dirname, ['book1.en_US.txt', 'book1.es_ES.txt', 'book2.zh_CN.txt'])

assert(v8.startupSnapshot.isBuildingSnapshot())
// Bei der Snapshot-Serialisierung werden die Bücher komprimiert, um die Größe zu reduzieren.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf)
// Bei der Snapshot-Deserialisierung werden die Bücher dekomprimiert.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf)
v8.startupSnapshot.setDeserializeMainFunction(shelf => {
  // process.env und process.argv werden während der Snapshot-
  // Deserialisierung aktualisiert.
  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)

Die resultierende Binärdatei gibt die Daten aus, die während des Starts aus dem Snapshot deserialisiert wurden, wobei die aktualisierten process.env und process.argv des gestarteten Prozesses verwendet werden:

bash
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Gibt den Inhalt von book1.es_ES.txt aus, der aus dem Snapshot deserialisiert wurde. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}

Derzeit kann die aus einem Userland-Snapshot deserialisierte Anwendung nicht erneut gesnapshotet werden, sodass diese APIs nur für Anwendungen verfügbar sind, die nicht aus einem Userland-Snapshot deserialisiert werden.

v8.startupSnapshot.addSerializeCallback(callback[, data])

Hinzugefügt in: v18.6.0, v16.17.0

  • callback <Funktion> Callback, der vor der Serialisierung aufgerufen wird.
  • data <any> Optionale Daten, die an den callback übergeben werden, wenn er aufgerufen wird.

Fügt einen Callback hinzu, der aufgerufen wird, wenn die Node.js-Instanz in einen Snapshot serialisiert und beendet wird. Dies kann verwendet werden, um Ressourcen freizugeben, die nicht serialisiert werden sollten oder können, oder um Benutzerdaten in eine für die Serialisierung besser geeignete Form zu konvertieren.

Callbacks werden in der Reihenfolge ausgeführt, in der sie hinzugefügt werden.

v8.startupSnapshot.addDeserializeCallback(callback[, data])

Hinzugefügt in: v18.6.0, v16.17.0

  • callback <Funktion> Callback, der nach der Deserialisierung des Snapshots aufgerufen wird.
  • data <any> Optionale Daten, die an den callback übergeben werden, wenn er aufgerufen wird.

Fügt einen Callback hinzu, der aufgerufen wird, wenn die Node.js-Instanz aus einem Snapshot deserialisiert wird. Der callback und die data (falls vorhanden) werden in den Snapshot serialisiert. Sie können verwendet werden, um den Status der Anwendung neu zu initialisieren oder Ressourcen erneut zu beziehen, die die Anwendung benötigt, wenn die Anwendung aus dem Snapshot neu gestartet wird.

Callbacks werden in der Reihenfolge ausgeführt, in der sie hinzugefügt werden.

v8.startupSnapshot.setDeserializeMainFunction(callback[, data])

Hinzugefügt in: v18.6.0, v16.17.0

  • callback <Funktion> Callback, der als Einstiegspunkt aufgerufen wird, nachdem der Snapshot deserialisiert wurde.
  • data <any> Optionale Daten, die an den callback übergeben werden, wenn er aufgerufen wird.

Dies legt den Einstiegspunkt der Node.js-Anwendung fest, wenn sie aus einem Snapshot deserialisiert wird. Dies kann nur einmal im Snapshot-Erstellungsskript aufgerufen werden. Wenn dies aufgerufen wird, benötigt die deserialisierte Anwendung kein zusätzliches Einstiegspunkt-Skript mehr zum Starten und ruft einfach den Callback zusammen mit den deserialisierten Daten (falls vorhanden) auf. Andernfalls muss der deserialisierten Anwendung immer noch ein Einstiegspunkt-Skript bereitgestellt werden.

v8.startupSnapshot.isBuildingSnapshot()

Hinzugefügt in: v18.6.0, v16.17.0

Gibt true zurück, wenn die Node.js-Instanz ausgeführt wird, um einen Snapshot zu erstellen.

Klasse: v8.GCProfiler

Hinzugefügt in: v19.6.0, v18.15.0

Diese API sammelt GC-Daten im aktuellen Thread.

new v8.GCProfiler()

Hinzugefügt in: v19.6.0, v18.15.0

Erstellt eine neue Instanz der Klasse v8.GCProfiler.

profiler.start()

Hinzugefügt in: v19.6.0, v18.15.0

Startet das Sammeln von GC-Daten.

profiler.stop()

Hinzugefügt in: v19.6.0, v18.15.0

Beendet das Sammeln von GC-Daten und gibt ein Objekt zurück. Der Inhalt des Objekts ist wie folgt:

json
{
  "version": 1,
  "startTime": 1674059033862,
  "statistics": [
    {
      "gcType": "Scavenge",
      "beforeGC": {
        "heapStatistics": {
          "totalHeapSize": 5005312,
          "totalHeapSizeExecutable": 524288,
          "totalPhysicalSize": 5226496,
          "totalAvailableSize": 4341325216,
          "totalGlobalHandlesSize": 8192,
          "usedGlobalHandlesSize": 2112,
          "usedHeapSize": 4883840,
          "heapSizeLimit": 4345298944,
          "mallocedMemory": 254128,
          "externalMemory": 225138,
          "peakMallocedMemory": 181760
        },
        "heapSpaceStatistics": [
          {
            "spaceName": "read_only_space",
            "spaceSize": 0,
            "spaceUsedSize": 0,
            "spaceAvailableSize": 0,
            "physicalSpaceSize": 0
          }
        ]
      },
      "cost": 1574.14,
      "afterGC": {
        "heapStatistics": {
          "totalHeapSize": 6053888,
          "totalHeapSizeExecutable": 524288,
          "totalPhysicalSize": 5500928,
          "totalAvailableSize": 4341101384,
          "totalGlobalHandlesSize": 8192,
          "usedGlobalHandlesSize": 2112,
          "usedHeapSize": 4059096,
          "heapSizeLimit": 4345298944,
          "mallocedMemory": 254128,
          "externalMemory": 225138,
          "peakMallocedMemory": 181760
        },
        "heapSpaceStatistics": [
          {
            "spaceName": "read_only_space",
            "spaceSize": 0,
            "spaceUsedSize": 0,
            "spaceAvailableSize": 0,
            "physicalSpaceSize": 0
          }
        ]
      }
    }
  ],
  "endTime": 1674059036865
}

Hier ist ein Beispiel.

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