Format de fichier instantané du tas
L’examen de l’utilisation de la mémoire dans les applications web peut être difficile. L’outil Mémoire DevTools vous permet d’explorer tous les objets alloués en mémoire par votre application web en prenant un tas instantané. Ces informations sont utiles pour les enquêtes sur les performances, car vous pouvez déterminer quels objets consomment le plus de mémoire.
Toutefois, vous devrez parfois vous concentrer sur des parties spécifiques des données mémoire que l’outil Mémoire n’affiche pas. Dans ce cas, utilisez DevTools pour exporter l’ensemble des données mémoire sous forme de .heapsnapshot
fichier JSON.
Cet article décrit la structure et le contenu des .heapsnapshot
fichiers JSON afin que vous puissiez créer vos propres outils de visualisation et d’analyse.
Enregistrer un tas instantané
Pour exporter un .heapsnapshot
fichier, vous devez d’abord enregistrer un tas instantané dans l’outil Mémoire, comme suit :
Dans Microsoft Edge, accédez au site web à partir duquel vous souhaitez exporter les données.
Appuyez sur Ctrl+Maj+I (Windows, Linux) ou Cmd+Option+I (macOS) pour ouvrir Devtools.
Ouvrez l’outil Mémoire .
Sélectionnez Heap instantané, puis cliquez sur Prendre instantané.
Pour plus d’informations, consultez Enregistrer des instantanés de segment de mémoire à l’aide de l’outil mémoire (« Type de profilage de tas instantané ») .
Exporter et afficher un .heapsnapshot
fichier
Une fois que vous avez enregistré un tas instantané, vous pouvez l’exporter.
Dans la barre latérale gauche de l’outil Mémoire, cliquez sur Enregistrer en regard du tas instantané élément que vous venez d’enregistrer.
Remplacez l’extension de fichier par
.heapsnapshot
.json
, pour faciliter l’ouverture du fichier dans un éditeur de texte.Ouvrez le fichier enregistré dans un éditeur de texte, par exemple Visual Studio Code.
Pour faciliter la lecture du json, dans Visual Studio Code, cliquez avec le bouton droit n’importe où dans le code, puis sélectionnez Mettre en forme le document.
En règle générale, le fichier obtenu .heapsnapshot
est différent chaque fois que vous enregistrez et exportez un tas instantané. Les instantanés de tas sont générés dynamiquement, en fonction du contenu de l’application web actuellement inspectée dans DevTools.
Vue d’ensemble du format de .heapsnapshot
fichier
La mémoire utilisée par une application web est organisée sous forme de graphe par V8, qui est le moteur JavaScript utilisé par Microsoft Edge. Un graphe est un type de données composé de nœuds (points sur le graphe) et d’arêtes (liens entre les points).
Les données contenues dans le .heapsnapshot
fichier représentent la mémoire de l’application web qui graphique efficacement et facilitent le transfert de groupes de données entre le processus du navigateur et DevTools. Le .heapsnapshot
fichier contient une représentation aplatissement des relations entre les nœuds et les arêtes, sous la forme d’un objet JSON qui contient des tableaux de nombres et de chaînes. Le fichier a une .heapsnapshot
extension de nom de fichier et contient des données au format JSON.
Les données ont deux parties main :
- Les métadonnées, qui contiennent toutes les informations dont vous avez besoin pour analyser les tableaux de données qui représentent le graphique mémoire.
- Les données des tableaux, qui contiennent les données réelles nécessaires à la recréation du graphe.
Mise à jour de cette documentation de format de données
Le format du .heapsnapshot
fichier, comme indiqué ci-dessous, peut changer à mesure que V8 et DevTools évoluent. Si vous constatez une différence dans la documentation, envoyez vos commentaires dans le référentiel MicrosoftDocs/edge-developer.
Schéma des .heapsnapshot
données
Structure de niveau supérieur
Les .heapsnapshot
données JSON contiennent un objet racine qui a les propriétés suivantes :
{
"snapshot": {},
"nodes": [],
"edges": [],
"trace_function_infos": [],
"trace_tree": [],
"samples": [],
"locations": [],
"strings": []
}
Propriété | Description | Format |
---|---|---|
snapshot |
Contient toutes les informations sur le format des données du graphique en mémoire et leur taille. | Object |
nodes |
Toutes les informations nécessaires pour recréer les nœuds du graphe. Pour analyser ces données, utilisez snapshot.meta.node_types et snapshot.meta.node_fields . |
Array |
edges |
Toutes les informations nécessaires pour recréer les arêtes du graphe. Pour analyser ces données, utilisez snapshot.meta.edge_types et snapshot.meta.edge_fields . |
Array |
trace_function_infos |
Pas encore documenté | Array |
trace_tree |
Pas encore documenté | Array |
samples |
Pas encore documenté | Array |
locations |
Contient des informations sur l’emplacement du script des nœuds. Pour analyser ces données, utilisez snapshot.meta.location_fields avec le nodes tableau . |
Array |
strings |
Tableau de toutes les chaînes conservées en mémoire. Il peut s’agir de chaînes, telles que des chaînes définies par l’utilisateur ou du code. | Array |
Instantané
{
"snapshot": {
"meta": {},
"node_count": 123,
"edge_count": 456,
"trace_function_count": 0
}
...
}
Propriété | Description | Format |
---|---|---|
meta |
Propriétés qui contiennent des informations sur la forme et la taille de chaque objet contenu dans les données du graphique en mémoire. | Object |
node_count |
Nombre total de nœuds dans le graphique mémoire. | Number |
edge_count |
Nombre total d’arêtes dans le graphique mémoire. | Number |
trace_function_count |
Nombre total de fonctions de trace dans le graphique mémoire. | Number |
Métadonnées d’instantané
{
"snapshot": {
"meta": {
"node_fields": [],
"node_types": [],
"edge_fields": [],
"edge_types": []
}
}
...
}
Propriété | Description | Format |
---|---|---|
node_fields |
Liste de toutes les propriétés requises pour recréer un nœud. | Array |
node_types |
Types de toutes les propriétés requises pour recréer un nœud. Le nombre de types est identique au nombre de propriétés définies dans node_fields . |
Array |
edge_fields |
Liste de toutes les propriétés requises pour recréer une arête. | Array |
edge_types |
Types de toutes les propriétés requises pour recréer une arête. Le nombre de types est identique au nombre de propriétés dans edge_fields . |
Array |
Voici un exemple d’objet de métadonnées :
{
"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
Le nodes
tableau, qui se trouve au niveau supérieur des .heapsnapshot
données, contient toutes les informations nécessaires pour recréer les nœuds du graphe de mémoire.
Pour analyser ce tableau, les informations suivantes sont nécessaires :
-
snapshot.node_count
, pour connaître le nombre de nœuds. -
snapshot.meta.node_fields
, pour connaître le nombre de champs de chaque nœud.
Chaque nœud du tableau est représenté par une série de snapshot.meta.node_fields.length
nombres. Par conséquent, le nombre total d’éléments dans le nodes
tableau est snapshot.node_count
multiplié par snapshot.meta.node_fields.length
.
Pour recréer un nœud, lisez les nombres du nodes
tableau par groupes de taille snapshot.meta.node_fields.length
.
L’extrait de code suivant montre les node_fields
métadonnées et les données des deux premiers nœuds du graphe :
{
"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 dans le groupe de nœuds | Nom | Description |
---|---|---|
0 |
type |
Type de nœud. Consultez Types de nœuds ci-dessous. |
1 |
name |
Nom du nœud. Il s’agit d’un nombre qui est l’index dans le tableau de niveau strings supérieur. Pour trouver le nom réel, utilisez le numéro d’index pour rechercher la chaîne dans le tableau de niveau strings supérieur. |
2 |
id |
ID unique du nœud. |
3 |
self_size |
Taille du nœud en octets. |
4 |
edge_count |
Nombre d’arêtes connectées à ce nœud. |
5 |
trace_node_id |
ID du nœud de trace |
6 |
detachedness |
Indique si ce nœud est accessible à partir de l’objet window global.
0 signifie que le nœud n’est pas détaché ; le nœud est accessible à partir de l’objet window global.
1 signifie que le nœud est détaché ; Le nœud n’est pas accessible à partir de l’objet window global. |
Types de nœuds
Le premier nombre du groupe de nombres d’un nœud du nodes
tableau correspond à son type. Ce nombre est un index qui peut être utilisé pour rechercher le nom du type dans le snapshot.meta.node_types[0]
tableau.
Type de nœud | Description |
---|---|
Masqué | Élément interne V8 qui ne correspond pas directement à un objet JavaScript contrôlable par l’utilisateur. Dans DevTools, tous ces éléments s’affichent sous le nom de catégorie (système). Même si ces objets sont internes, ils peuvent être une partie importante des chemins de rétention. |
Objet | Tout objet défini par l’utilisateur, tel que { x: 2 } ou new Foo(4) . Les contextes, qui apparaissent dans DevTools en tant que système/contexte, contiennent des variables qui devaient être allouées sur le tas, car elles sont utilisées par une fonction imbriquée. |
Natif | Éléments alloués par le moteur de rendu Blink, plutôt que par V8. Il s’agit principalement d’éléments DOM tels que HTMLDivElement ou CSSStyleRule . |
Chaîne concaténée | Résultat de la concaténation de deux chaînes avec l’opérateur + . Au lieu de créer une nouvelle chaîne contenant une copie de toutes les données des deux chaînes sources, V8 crée un ConsString objet qui contient des pointeurs vers les deux chaînes sources. Du point de vue de JavaScript, il agit comme n’importe quelle autre chaîne, mais du point de vue du profilage de la mémoire, il est différent. |
Chaîne segmentée | Résultat d’une opération de sous-chaîne, telle que l’utilisation String.prototype.substr de ou String.prototype.substring . V8 évite de copier des données de chaîne en créant à la place un SlicedString , qui pointe vers la chaîne d’origine et spécifie l’index de début et la longueur. Du point de vue JavaScript, une chaîne segmentée agit comme n’importe quelle autre chaîne, mais du point de vue du profilage de la mémoire, elle est différente. |
Tableau | Différentes listes internes, qui sont affichées dans DevTools avec le nom de catégorie (tableau). Comme Hidden, cette catégorie regroupe une variété d’éléments. La plupart des objets ici sont nommés (propriétés de l’objet) ou (éléments d’objet), ce qui indique qu’ils contiennent les propriétés à clé de chaîne ou à clé numérique d’un objet JavaScript. |
Code | Éléments qui augmentent proportionnellement à la quantité de script et/ou au nombre d’exécutions des fonctions. |
Synthétique | Les nœuds synthétiques ne correspondent pas à quoi que ce soit réellement alloué en mémoire. Ils sont utilisés pour distinguer les différents types de racines de garbage collection (GC). |
Bords
À l’instar du nodes
tableau, le edges
tableau de niveau supérieur contient tous les éléments nécessaires pour recréer les bords du graphe de mémoire.
De même que pour les nœuds, le nombre total d’arêtes peut être calculé en multipliant snapshot.edge_count
par snapshot.meta.edge_fields.length
. Les arêtes sont également stockées sous la forme d’une séquence de nombres, sur lesquelles vous devrez itérer par groupes de taille snapshot.meta.edge_fields.length
.
Toutefois, pour lire correctement le edges
tableau, vous devez d’abord lire le nodes
tableau, car chaque nœud sait combien d’arêtes il possède.
Pour recréer une arête, vous avez besoin de trois informations :
- Type d’arête.
- Nom ou index de l’arête.
- Nœud auquel le bord est connecté.
Par exemple, si vous lisez le premier nœud du nodes
tableau et que sa edge_count
propriété est définie sur 4, les quatre premiers groupes de snapshot.meta.edge_fields.length
nombres du edges
tableau correspondent aux quatre bords de ce nœud.
Index dans le groupe edge | Nom | Description |
---|---|---|
0 |
type |
Type de bord. Consultez Types Edge pour savoir quels sont les types possibles. |
1 |
name_or_index |
Il peut s’agir d’un nombre ou d’une chaîne. S’il s’agit d’un nombre, il correspond à l’index dans le tableau de niveau strings supérieur, où se trouve le nom de l’arête. |
2 |
to_node |
Index dans le nodes tableau auquel cette arête est connectée. |
Types d’arêtes
Le premier nombre du groupe de nombres d’une arête dans le edges
tableau correspond à son type. Ce nombre est un index qui peut être utilisé pour rechercher le nom du type dans le snapshot.meta.edge_types[0]
tableau.
Type d’arête | Description |
---|---|
Interne | Les arêtes qui ne correspondent pas aux noms visibles par JavaScript, mais qui restent importantes. Par exemple, les instances de fonction ont un « contexte » représentant l’état des variables qui se trouvaient dans l’étendue où la fonction a été définie. Il n’existe aucun moyen pour le code JavaScript de lire directement le « contexte » d’une fonction, mais ces arêtes sont nécessaires lors de l’examen des rétentions. |
Faible | Les bords faibles ne conservent pas le nœud auquel ils sont connectés et sont donc omis de la vue Des rétentions. Tout objet avec des bords faibles pointant vers celui-ci peut être ignoré par le garbage collection (GC). |
Masqué | Comme interne, à l’exception de ces arêtes n’ont pas de noms uniques et sont numérotées dans l’ordre croissant. |
Raccourci | Représentation plus facile à lire d’un autre chemin d’accès. Ce type est rarement utilisé. Par exemple, si vous utilisez Function.prototype.bind pour créer une fonction liée avec des arguments liés, V8 crée un JSBoundFunction , qui pointe vers un FixedArray (un type interne), qui pointe vers chaque argument lié. Lors de la production d’un instantané, V8 ajoute un bord de raccourci de la fonction liée directement à chaque argument lié, en contournant .FixedArray |
Élément | Propriétés de l’objet où la clé est un nombre. |
emplacements
Le locations
tableau, qui se trouve au niveau supérieur des .heapsnapshot
données, contient des informations sur l’emplacement où certains nœuds du instantané ont été créés. Ce tableau se compose d’une série de nombres destinés à être lus par groupes de taille snapshot.meta.location_fields.length
. Par conséquent, nous allons accéder à snapshot.meta.location_fields
pour connaître le nombre de champs de chaque emplacement dans le locations
tableau et ce que sont ces champs. Par exemple, si location_fields
contient 4 éléments, le locations
tableau doit être lu par groupes de 4.
snapshot.meta.location_fields
contient les informations pour chaque emplacement :
Indexer dans location_fields |
Nom | Description |
---|---|---|
0 |
object_index |
Index du nœud dans le snapshot.nodes tableau associé à cet emplacement. |
1 |
script_id |
ID du script qui crée le nœud associé. |
2 |
line |
Numéro de ligne où le nœud a été créé, dans le script qui a créé le nœud. |
3 |
column |
Numéro de colonne dans lequel le nœud a été créé, dans le script qui a créé le nœud. |
L’exemple de code suivant montre comment lier le snapshot.locations
tableau au snapshot.nodes
tableau :
{
"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,
...
],
...
}
Le premier emplacement du locations
tableau est 7,9,0,0,
. Cet emplacement est associé au groupe d’informations de nœud qui commence à l’index 7 dans le nodes
tableau. Par conséquent, le nœud contient les paires clé/valeur suivantes :
"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,
Voir aussi
Pour en savoir plus sur le format de .heapsnapshot
fichier, consultez le code qui génère le fichier, qui est la HeapSnapshotGenerator
classe dans heap-snapshot-generator.h
.