Das Heap-Momentaufnahme-Dateiformat
Die Untersuchung der Speicherauslastung in Webanwendungen kann schwierig sein. Mit dem DevTools-Speichertool können Sie alle Objekte untersuchen, die von Ihrer Webanwendung im Arbeitsspeicher zugeordnet werden, indem Sie einen Heap Momentaufnahme. Diese Informationen sind für Leistungsuntersuchungen nützlich, da Sie herausfinden können, welche Objekte den meisten Arbeitsspeicher verbrauchen.
Manchmal müssen Sie sich jedoch auf bestimmte Teile der Speicherdaten konzentrieren, die vom Speichertool nicht angezeigt werden. Verwenden Sie in diesem Fall DevTools, um den gesamten Satz von Speicherdaten als .heapsnapshot
JSON-Datei zu exportieren.
In diesem Artikel werden die Struktur und der Inhalt von .heapsnapshot
JSON-Dateien beschrieben, damit Sie Ihre eigenen Visualisierungs- und Analysetools erstellen können.
Aufzeichnen eines Heaps Momentaufnahme
Um eine .heapsnapshot
Datei zu exportieren, müssen Sie zunächst wie folgt einen Heap-Momentaufnahme im Speichertool aufzeichnen:
Navigieren Sie in Microsoft Edge zu der Website, von der Sie die Daten exportieren möchten.
Drücken Sie STRG+UMSCHALT+I (Windows, Linux) oder BEFEHL+WAHL+I (macOS), um DevTools zu öffnen.
Öffnen Sie das Speichertool .
Wählen Sie Heap Momentaufnahme aus, und klicken Sie dann auf Momentaufnahme.
Weitere Informationen finden Sie unter Aufzeichnen von Heapmomentaufnahmen mit dem Speichertool ("Profilerstellungstyp Heap Momentaufnahme").
Exportieren und Anzeigen einer .heapsnapshot
Datei
Nachdem Sie einen Heap Momentaufnahme aufgezeichnet haben, können Sie ihn exportieren.
Klicken Sie in der linken Seitenleiste des Speichertools neben dem Heap Momentaufnahme soeben aufgezeichneten Elements auf Speichern.
Ändern Sie die Dateierweiterung von in
.heapsnapshot
.json
, um das Öffnen der Datei in einem Text-Editor zu vereinfachen.Öffnen Sie die gespeicherte Datei in einem Text-Editor, z. B. Visual Studio Code.
Um die Lesbarkeit des JSON-Codes zu vereinfachen, klicken Sie in Visual Studio Code mit der rechten Maustaste auf eine beliebige Stelle im Code, und wählen Sie dann Dokument formatieren aus.
Im Allgemeinen unterscheidet sich die resultierende .heapsnapshot
Datei jedes Mal, wenn Sie einen Heap Momentaufnahme aufzeichnen und exportieren. Heapmomentaufnahmen werden basierend auf dem Inhalt der Webanwendung, die derzeit in DevTools untersucht wird, dynamisch generiert.
Übersicht über das .heapsnapshot
Dateiformat
Der von einer Webanwendung verwendete Arbeitsspeicher wird von V8 als Graph organisiert. Dies ist die javaScript-Engine, die von Microsoft Edge verwendet wird. Ein Graph ist ein Datentyp, der aus Knoten (Punkten im Diagramm) und Kanten (Verknüpfungen zwischen den Punkten) besteht.
Die Daten in der .heapsnapshot
Datei stellen den Arbeitsspeicher der Web-App dar, der effizient graphisch dargestellt wird, und erleichtern die Übertragung von Datengruppen zwischen dem Browserprozess und DevTools. Die .heapsnapshot
Datei enthält eine vereinfachte Darstellung der Beziehungen zwischen Knoten und Kanten als JSON-Objekt, das Arrays von Zahlen und Zeichenfolgen enthält. Die Datei verfügt über eine .heapsnapshot
Dateinamenerweiterung und enthält Daten im JSON-Format.
Die Daten bestehen aus zwei Standard Teilen:
- Die Metadaten, die alle Informationen enthalten, die Sie benötigen, um die Arrays von Daten zu analysieren, die das Speicherdiagramm darstellen.
- Die Arraydaten, die die tatsächlichen Daten enthalten, die zum erneuten Erstellen des Graphen erforderlich sind.
Aktualisieren der Dokumentation zu diesem Datenformat
Das Format der .heapsnapshot
Datei, wie unten dokumentiert, kann sich mit der Weiterentwicklung von V8 und DevTools ändern. Wenn Sie eine Diskrepanz in der Dokumentation feststellen, senden Sie feedback im Repository MicrosoftDocs/edge-developer.
Schema der .heapsnapshot
Daten
Struktur der obersten Ebene
Die .heapsnapshot
JSON-Daten enthalten ein Stammobjekt mit den folgenden Eigenschaften:
{
"snapshot": {},
"nodes": [],
"edges": [],
"trace_function_infos": [],
"trace_tree": [],
"samples": [],
"locations": [],
"strings": []
}
Eigenschaft | Beschreibung | Format |
---|---|---|
snapshot |
Enthält alle Informationen zum Format der Speicherdiagrammdaten und deren Größe. | Object |
nodes |
Alle Informationen, die erforderlich sind, um die Knoten des Graphen neu zu erstellen. Um diese Daten zu analysieren, verwenden Sie snapshot.meta.node_types und snapshot.meta.node_fields . |
Array |
edges |
Alle Informationen, die erforderlich sind, um die Kanten des Graphen neu zu erstellen. Um diese Daten zu analysieren, verwenden Sie snapshot.meta.edge_types und snapshot.meta.edge_fields . |
Array |
trace_function_infos |
Noch nicht dokumentiert | Array |
trace_tree |
Noch nicht dokumentiert | Array |
samples |
Noch nicht dokumentiert | Array |
locations |
Enthält Informationen zum Skriptspeicherort von Knoten. Verwenden Sie snapshot.meta.location_fields zum Analysieren dieser Daten mit dem nodes Array. |
Array |
strings |
Ein Array aller Zeichenfolgen, die im Arbeitsspeicher gespeichert sind. Dabei kann es sich um beliebige Zeichenfolgen handeln, z. B. benutzerdefinierte Zeichenfolgen oder Code. | Array |
Snapshot
{
"snapshot": {
"meta": {},
"node_count": 123,
"edge_count": 456,
"trace_function_count": 0
}
...
}
Eigenschaft | Beschreibung | Format |
---|---|---|
meta |
Eigenschaften, die Informationen zur Form und Größe jedes Objekts enthalten, das in den Speicherdiagrammdaten enthalten ist. | Object |
node_count |
Die Gesamtanzahl der Knoten im Speicherdiagramm. | Number |
edge_count |
Die Gesamtanzahl der Kanten im Speicherdiagramm. | Number |
trace_function_count |
Die Gesamtanzahl der Ablaufverfolgungsfunktionen im Speicherdiagramm. | Number |
Momentaufnahmemetadaten
{
"snapshot": {
"meta": {
"node_fields": [],
"node_types": [],
"edge_fields": [],
"edge_types": []
}
}
...
}
Eigenschaft | Beschreibung | Format |
---|---|---|
node_fields |
Die Liste aller Eigenschaften, die zum erneuten Erstellen eines Knotens erforderlich sind. | Array |
node_types |
Die Typen aller Eigenschaften, die zum erneuten Erstellen eines Knotens erforderlich sind. Die Anzahl der Typen entspricht der Anzahl der in node_fields definierten Eigenschaften. |
Array |
edge_fields |
Die Liste aller Eigenschaften, die zum erneuten Erstellen eines Edges erforderlich sind. | Array |
edge_types |
Die Typen aller Eigenschaften, die zum erneuten Erstellen eines Edges erforderlich sind. Die Anzahl der Typen entspricht der Anzahl der Eigenschaften in edge_fields . |
Array |
Es folgt ein Beispiel für ein Metadatenobjekt:
{
"snapshot": {
"meta": {
"node_fields": [
"type",
"name",
"id",
"self_size",
"edge_count",
"trace_node_id",
"detachedness"
],
"node_types": [
[
"hidden",
"array",
"string",
"object",
"code",
"closure",
"regexp",
"number",
"native",
"synthetic",
"concatenated string",
"sliced string",
"symbol",
"bigint",
"object shape"
],
"string",
"number",
"number",
"number",
"number",
"number"
],
"edge_fields": [
"type",
"name_or_index",
"to_node"
],
"edge_types": [
[
"context",
"element",
"property",
"internal",
"hidden",
"shortcut",
"weak"
],
"string_or_number",
"node"
]
}
}
}
Nodes
Das nodes
Array, das sich auf der obersten Ebene der .heapsnapshot
Daten befindet, enthält alle Informationen, die erforderlich sind, um die Knoten des Speicherdiagramms neu zu erstellen.
Zum Analysieren dieses Arrays sind die folgenden Informationen erforderlich:
-
snapshot.node_count
, um zu wissen, wie viele Knoten es gibt. -
snapshot.meta.node_fields
, um zu wissen, über wie viele Felder jeder Knoten verfügt.
Jeder Knoten im Array wird durch eine Reihe von snapshot.meta.node_fields.length
Zahlen dargestellt. Die Gesamtzahl der Elemente im nodes
Array wird snapshot.node_count
also mit snapshot.meta.node_fields.length
multipliziert.
Um einen Knoten neu zu erstellen, lesen Sie die Zahlen aus dem nodes
Array nach Gruppen der Größe snapshot.meta.node_fields.length
.
Der folgende Codeausschnitt zeigt die node_fields
Metadaten und die Daten für die ersten beiden Knoten im Diagramm:
{
"snapshot": {
"meta": {
"node_fields": [
"type",
"name",
"id",
"self_size",
"edge_count",
"trace_node_id",
"detachedness"
]
...
}
...
},
"nodes": [
9,1,1,0,10,0,0,
2,1,79,12,1,0,0,
...
]
...
}
Index in Knotengruppe | Name | Beschreibung |
---|---|---|
0 |
type |
Der Typ des Knotens. Weitere Informationen finden Sie weiter unten unter Knotentypen. |
1 |
name |
Der Name des Knotens. Dies ist eine Zahl, die den Index im Array der obersten Ebene strings darstellt. Um den tatsächlichen Namen zu finden, verwenden Sie die Indexnummer, um die Zeichenfolge im Array der obersten Ebene strings nachzuschlagen. |
2 |
id |
Die eindeutige ID des Knotens. |
3 |
self_size |
Die Größe des Knotens in Bytes. |
4 |
edge_count |
Die Anzahl von Edges, die mit diesem Knoten verbunden sind. |
5 |
trace_node_id |
Die ID des Ablaufverfolgungsknotens |
6 |
detachedness |
Gibt an, ob dieser Knoten vom globalen Objekt aus window erreicht werden kann.
0 bedeutet, dass der Knoten nicht getrennt ist; Der Knoten kann vom globalen Objekt aus window erreicht werden.
1 bedeutet, dass der Knoten getrennt ist; Der Knoten kann vom window globalen Objekt nicht erreicht werden. |
Knotentypen
Die erste Zahl in der Gruppe von Zahlen für einen Knoten im nodes
Array entspricht ihrem Typ. Diese Zahl ist ein Index, der verwendet werden kann, um den Typnamen im snapshot.meta.node_types[0]
Array zu suchen.
Knotentyp | Beschreibung |
---|---|
Ausgeblendet | Ein internes V8-Element, das nicht direkt einem vom Benutzer steuerbaren JavaScript-Objekt entspricht. In DevTools werden diese unter dem Kategorienamen (System) angezeigt. Obwohl diese Objekte intern sind, können sie ein wichtiger Bestandteil von Aufbewahrungspfaden sein. |
Objekt | Jedes benutzerdefinierte Objekt, z { x: 2 } . B. oder new Foo(4) . Kontexte, die in DevTools als System/Kontext angezeigt werden, enthalten Variablen, die auf dem Heap zugeordnet werden mussten, da sie von einer geschachtelten Funktion verwendet werden. |
Systemeigen | Elemente, die von der Blink-Rendering-Engine und nicht von V8 zugeordnet werden. Dies sind hauptsächlich DOM-Elemente wie HTMLDivElement oder CSSStyleRule . |
Verkettete Zeichenfolge | Das Ergebnis der Verkettung von zwei Zeichenfolgen mit dem + Operator. Anstatt eine neue Zeichenfolge zu erstellen, die eine Kopie aller Daten aus den beiden Quellzeichenfolgen enthält, erstellt V8 ein ConsString -Objekt, das Zeiger auf die beiden Quellzeichenfolgen enthält. Aus JavaScript-Sicht verhält es sich wie jede andere Zeichenfolge, aber aus Sicht der Speicherprofilerstellung ist es anders. |
Zeichenfolge mit Datenschnitt | Das Ergebnis einer Teilzeichenfolgenoperation, z. B. mit String.prototype.substr oder String.prototype.substring . V8 vermeidet das Kopieren von Zeichenfolgendaten, indem stattdessen ein SlicedString erstellt wird, der auf die ursprüngliche Zeichenfolge verweist und den Anfangsindex und die Länge angibt. Aus JavaScript-Sicht verhält sich eine Zeichenfolge mit Datenschnitt wie jede andere Zeichenfolge, aber aus Sicht der Speicherprofilerstellung ist sie anders. |
Array | Verschiedene interne Listen, die in DevTools mit dem Kategorienamen (Array) angezeigt werden. Wie Ausgeblendet gruppiert diese Kategorie eine Vielzahl von Dingen. Viele der hier aufgeführten Objekte sind benannt (Objekteigenschaften) oder (Objektelemente), was angibt, dass sie die Eigenschaften mit Zeichenfolgenschlüssel oder numerischen Schlüsseln eines JavaScript-Objekts enthalten. |
Code | Dinge, die proportional zur Menge des Skripts und/oder zur Häufigkeit der Ausführung von Funktionen wachsen. |
Synthetisch | Synthetische Knoten entsprechen nichts, was tatsächlich im Arbeitsspeicher zugeordnet ist. Diese werden verwendet, um die verschiedenen Arten von Garbage Collection-Wurzeln (GC) zu unterscheiden. |
Kanten
Ähnlich wie das nodes
-Array enthält das Array der edges
obersten Ebene alle Elemente, die zum neu erstellen der Ränder des Speicherdiagramms erforderlich sind.
Ähnlich wie bei Knoten kann die Gesamtanzahl der Kanten durch Multiplizieren snapshot.edge_count
mit snapshot.meta.edge_fields.length
berechnet werden. Kanten werden auch als Sequenz von Zahlen gespeichert, die Sie nach Gruppen der Größe snapshot.meta.edge_fields.length
durchlaufen müssen.
Um das edges
Array richtig zu lesen, müssen Sie jedoch zuerst das nodes
Array lesen, da jeder Knoten weiß, wie viele Kanten er hat.
Um einen Edge neu zu erstellen, benötigen Sie drei Informationen:
- Der Edgetyp.
- Der Edgename oder -index.
- Der Knoten, mit dem der Edge verbunden ist.
Wenn Sie z. B. den ersten Knoten im nodes
Array lesen und dessen edge_count
Eigenschaft auf 4 festgelegt ist, entsprechen die ersten vier Zahlengruppen snapshot.meta.edge_fields.length
im edges
Array den vier Kanten dieses Knotens.
Index in Edgegruppe | Name | Beschreibung |
---|---|---|
0 |
type |
Der Typ des Edges. Informationen zu den möglichen Typen finden Sie unter Edgetypen . |
1 |
name_or_index |
Dies kann eine Zahl oder eine Zeichenfolge sein. Wenn es sich um eine Zahl handelt, entspricht sie dem Index im Array der obersten Ebene strings , in dem der Name des Edges gefunden werden kann. |
2 |
to_node |
Der Index innerhalb des nodes Arrays, mit dem dieser Edge verbunden ist. |
Edgetypen
Die erste Zahl in der Gruppe von Zahlen für eine Kante im edges
Array entspricht ihrem Typ. Diese Zahl ist ein Index, der verwendet werden kann, um den Typnamen im snapshot.meta.edge_types[0]
Array zu suchen.
Edgetyp | Beschreibung |
---|---|
Intern | Kanten, die nicht mit JavaScript sichtbaren Namen übereinstimmen, aber dennoch wichtig sind. Funktionsinstanzen verfügen beispielsweise über einen "Kontext", der den Zustand von Variablen darstellt, die sich im Bereich befanden, in dem die Funktion definiert wurde. Es gibt keine Möglichkeit für JavaScript-Code, den "Kontext" einer Funktion direkt zu lesen, aber diese Kanten sind für die Untersuchung von Aufbewahrungen erforderlich. |
Schwach | Schwache Kanten halten den Knoten, mit dem sie verbunden sind, nicht aktiv und werden daher in der Ansicht Aufbewahrungen ausgelassen. Jedes Objekt mit nur schwachen Kanten, die darauf verweisen, kann von der Garbage Collection (GC) verworfen werden. |
Ausgeblendet | Ähnlich wie intern, mit der Ausnahme, dass diese Kanten keine eindeutigen Namen haben und stattdessen in zunehmender Reihenfolge nummeriert werden. |
Verknüpfung | Eine einfacher zu lesende Darstellung eines anderen Pfads. Dieser Typ wird selten verwendet. Wenn Sie beispielsweise verwenden Function.prototype.bind , um eine gebundene Funktion mit einigen gebundenen Argumenten zu erstellen, erstellt V8 ein JSBoundFunction , das auf ein FixedArray (einen internen Typ) zeigt, der auf jedes gebundene Argument verweist. Beim Erstellen eines Momentaufnahme fügt V8 jedem gebundenen Argument eine Verknüpfungskante aus der gebundenen Funktion direkt hinzu, wobei das umgangen wirdFixedArray . |
Element | Objekteigenschaften, bei denen der Schlüssel eine Zahl ist. |
locations
Das locations
Array, das sich auf der obersten Ebene der .heapsnapshot
Daten befindet, enthält Informationen darüber, wo einige der Knoten im Momentaufnahme erstellt wurden. Dieses Array besteht aus einer Reihe von Zahlen, die von Gruppen der Größe snapshot.meta.location_fields.length
gelesen werden sollen. Daher würden wir zu snapshot.meta.location_fields
gehen, um zu wissen, wie viele Felder jeder Standort im locations
Array hat und was diese Felder sind. Wenn location_fields
beispielsweise 4 Elemente enthalten sind, sollte das locations
Array von Gruppen von 4 gelesen werden.
snapshot.meta.location_fields
enthält die Informationen für jeden Speicherort:
Index in location_fields |
Name | Beschreibung |
---|---|---|
0 |
object_index |
Der Index des Knotens in dem snapshot.nodes Array, das dieser Position zugeordnet ist. |
1 |
script_id |
Die ID des Skripts, das den zugeordneten Knoten erstellt. |
2 |
line |
Die Zeilennummer, in der der Knoten innerhalb des Skripts erstellt wurde, mit dem der Knoten erstellt wurde. |
3 |
column |
Die Spaltennummer, in der der Knoten innerhalb des Skripts erstellt wurde, mit dem der Knoten erstellt wurde. |
Im folgenden Codebeispiel wird gezeigt, wie das snapshot.locations
Array mit dem snapshot.nodes
Array verknüpft wird:
{
"snapshot": {
"meta": {
"location_fields": [
"object_index",
"script_id",
"line",
"column"
]
...
}
...
},
"nodes": [
9,1,1,0,10,0,0,
2,1,79,12,1,0,0,
...
],
"locations":[
7,9,0,0,
113792,3,25,21,
...
],
...
}
Die erste Position im locations
Array ist 7,9,0,0,
. Dieser Speicherort ist der Knoteninformationsgruppe zugeordnet, die bei Index 7 im nodes
Array beginnt. Daher enthält der Knoten die folgenden Schlüssel-Wert-Paare:
"type": 2,
"name": 1,
"id": 79,
"self_size": 12,
"edge_count": 1,
"trace_node_id": 0,
"detachedness": 0,
"script_id": 9,
"line" 0,
"column": 0,
Siehe auch
Weitere Informationen zum .heapsnapshot
Dateiformat finden Sie im Code, der die Datei generiert. Dabei handelt es sich um die HeapSnapshotGenerator
-Klasse in heap-snapshot-generator.h
.