Enregistrer des instantanés de tas à l’aide de l’outil Mémoire (type de profilage « Tas instantané »)
Utilisez le profileur de tas dans l’outil Mémoire pour effectuer les opérations suivantes :
- Enregistrez des captures instantanées de tas JavaScript (tas JS).
- Analyser les graphiques de mémoire.
- Comparer les instantanés.
- Rechercher les fuites de mémoire.
Le profileur de tas DevTools affiche la distribution de mémoire utilisée par les objets JavaScript et par les nœuds DOM associés sur la page web rendue.
Prendre un instantané
Ouvrez la page web que vous souhaitez analyser. Par exemple, ouvrez la page de démonstration Objets dispersés dans une nouvelle fenêtre ou un nouvel onglet.
Pour ouvrir DevTools, cliquez avec le bouton droit sur la page web, puis sélectionnez Inspecter. Vous pouvez également appuyer sur Ctrl+Maj+I (Windows, Linux) ou Cmd+Option+I (macOS). DevTools s’ouvre.
Dans DevTools, dans la barre d’activité, sélectionnez l’onglet Mémoire . Si cet onglet n’est pas visible, cliquez sur le bouton Autres outils ().
Dans la section Sélectionner le type de profilage, sélectionnez le bouton d’option Tas instantané.
Sous Sélectionner une machine virtuelle JavaScript instance, sélectionnez la machine virtuelle JavaScript que vous souhaitez profiler.
Cliquez sur le bouton Prendre instantané :
Une fois que le instantané de segment de mémoire nouvellement enregistré a été chargé dans DevTools et analysé, le instantané s’affiche et une nouvelle entrée s’affiche dans la barre latérale Profils sous Instantanés du tas :
Le numéro sous le nouvel élément de barre latérale indique la taille totale des objets JavaScript accessibles. Pour en savoir plus sur les tailles d’objet dans le tas instantané, consultez Tailles et distances des objets dans la terminologie mémoire.
Le instantané affiche uniquement les objets du graphique mémoire accessibles à partir de l’objet global. La prise d’une instantané commence toujours par un garbage collection.
Prenez une autre instantané
Pour prendre une autre instantané lorsqu’un est déjà affiché dans l’outil Mémoire, dans la barre latérale, cliquez sur Profils au-dessus du instantané existant :
Effacer les instantanés
Pour effacer tous les instantanés de l’outil Mémoire , cliquez sur l’icône Effacer tous les profils () :
Afficher les instantanés
Les instantanés de tas peuvent être consultés de plusieurs façons différentes dans l’outil Mémoire . Chaque façon d’afficher un tas instantané dans l’interface utilisateur correspond à une tâche différente :
Afficher | Contenu | Utilisé pour |
---|---|---|
Résumé | Affiche les objets regroupés par nom de constructeur. | Recherche d’objets et de la mémoire qu’ils utilisent, en fonction des types regroupés par nom de constructeur. Utile pour le suivi des fuites DOM. |
Comparaison | Affiche les différences entre deux instantanés. | Comparaison de deux instantanés mémoire (ou plus) avant et après une opération. L’inspection du delta dans la mémoire libérée et l’inspection du nombre de références vous aident à confirmer la présence et la cause d’une fuite de mémoire, et à en déterminer la cause. |
Confinement | Permet l’exploration du contenu du tas. | Fournit une meilleure vue de la structure des objets, ce qui permet d’analyser les objets référencés dans l’espace de noms global (fenêtre) pour déterminer ce qui maintient les objets autour. Utilisez-le pour analyser les fermetures et plonger dans vos objets à un niveau inférieur. |
Pour basculer entre les vues, utilisez la liste déroulante en haut de l’outil Mémoire :
Éléments omis dans les instantanés de tas
Les propriétés implémentées à l’aide de getters qui exécutent du code natif ne sont pas capturées dans le tas instantané, car ces propriétés ne sont pas stockées sur le tas JavaScript.
Les valeurs non-chaînes, telles que les nombres, ne sont pas capturées.
Vue récapitulative
L’affichage Résumé de l’outil Mémoire répertorie les éléments suivants :
- Groupes de constructeurs d’objets.
- Noms de catégorie spéciaux, tels que (tableau),(code compilé), ou une liste de propriétés telles que {foo, bar, baz}.
Au départ, un tas instantané s’ouvre dans la vue Résumé, qui affiche une liste de constructeurs :
Chaque constructeur de la liste peut être développé pour afficher les objets qui ont été instanciés à l’aide de ce constructeur.
Pour chaque constructeur de la liste, la vue Résumé affiche également un nombre tel que ×123, indiquant le nombre total d’objets créés avec le constructeur. La vue Résumé affiche également les colonnes suivantes :
Nom de colonne | Description |
---|---|
Distance | Affiche la distance à la racine à l’aide du chemin d’accès simple le plus court des nœuds. Consultez La terminologie distance dans la mémoire. |
Taille superficielle | Affiche la somme des tailles superficielles de tous les objets créés par une fonction de constructeur spécifique. La taille superficielle est la taille du tas JavaScript qui est directement détenu par un objet. La taille superficielle d’un objet est généralement petite, car un objet JavaScript stocke souvent uniquement sa description de l’objet, et non les valeurs, dans la mémoire directement détenue de l’objet. La plupart des objets JavaScript stockent leurs valeurs dans un magasin de stockage qui se trouve ailleurs dans le tas JavaScript et exposent uniquement un petit objet wrapper sur la partie du tas JavaScript qui appartient directement à l’objet. Consultez Taille superficielle dans la terminologie de la mémoire. |
Taille conservée | Affiche la taille maximale conservée parmi le même ensemble d’objets. La taille de la mémoire que vous pouvez libérer après la suppression d’un objet (et que les dépendants ne sont plus accessibles) est appelée taille conservée. Consultez Taille conservée dans la terminologie de la mémoire. |
Après avoir développé un constructeur dans la vue Résumé , toutes les instances du constructeur s’affichent. Pour chaque instance, les tailles superficielles et conservées sont affichées dans les colonnes correspondantes. Le nombre après le @
caractère est l’ID unique de l’objet, ce qui vous permet de comparer des instantanés de tas par objet.
Entrées de constructeur
L’affichage Résumé de l’outil Mémoire répertorie les groupes de constructeurs d’objets :
Les groupes de constructeurs dans la vue Résumé peuvent être des fonctions intégrées telles que Array
ou Object
, ou il peut s’agir de fonctions définies dans votre propre code.
Pour afficher la liste des objets qui ont été instanciés par un constructeur donné, développez le groupe de constructeurs.
Noms de catégorie spéciaux
La vue Résumé de l’outil Mémoire inclut les noms de catégories spéciales suivants, qui ne sont pas basés sur les constructeurs. La plupart de ces noms de catégorie sont affichés entre parenthèses.
Nom de catégorie | Description |
---|---|
(tableau) | Divers objets internes de type tableau qui ne correspondent pas directement aux objets visibles à partir de JavaScript, tels que le contenu des tableaux JavaScript ou les propriétés nommées des objets JavaScript. |
(code compilé) | Données internes dont V8 (moteur JavaScript de Microsoft Edge) a besoin pour exécuter des fonctions définies par JavaScript ou WebAssembly. V8 gère automatiquement l’utilisation de la mémoire dans cette catégorie : si une fonction s’exécute plusieurs fois, V8 utilise davantage de mémoire pour cette fonction afin que la fonction s’exécute plus rapidement. Si une fonction ne s’est pas exécutée depuis un certain temps, V8 peut supprimer les données internes de cette fonction. |
(chaîne concaténée) | Lorsque deux chaînes sont concaténées ensemble, comme lors de l’utilisation de l’opérateur JavaScript + , V8 peut choisir de représenter le résultat en interne sous la forme d’une chaîne concaténée. Au lieu de copier tous les caractères des deux chaînes dans une nouvelle chaîne, V8 crée un petit objet qui pointe vers les deux chaînes. |
(forme d’objet) | Informations sur les objets, telles que le nombre de propriétés qu’ils possèdent et une référence à leurs prototypes, que V8 gère en interne lors de la création et de la mise à jour des objets. Cela permet à V8 de représenter efficacement les objets avec les mêmes propriétés. |
(chaîne segmentée) | Lors de la création d’une sous-chaîne, par exemple lors de l’utilisation de la méthode JavaScript substring , V8 peut choisir de créer un objet de chaîne segmentée plutôt que de copier tous les caractères pertinents de la chaîne d’origine. Ce nouvel objet contient un pointeur vers la chaîne d’origine et décrit la plage de caractères de la chaîne d’origine à utiliser. |
(système) | Divers objets internes qui n’ont pas encore été classés de manière plus significative. |
{foo, bar, baz} | Objets JavaScript bruts classés par interface (liste de propriétés), en accolades. Les objets JavaScript bruts ne sont pas répertoriés dans une catégorie nommée Object, mais sont représentés par des noms et des catégories basés sur les propriétés que l’objet contient, telles que {foo, bar, baz}. |
InternalNode | Objets alloués en dehors de V8, tels que les objets C++ définis par Blink, le moteur de rendu de Microsoft Edge. |
system / Context | Variables locales à partir d’une étendue JavaScript accessible par une fonction imbriquée. Chaque fonction instance contient un pointeur interne vers le contexte dans lequel elle s’exécute, afin qu’elle puisse accéder à ces variables. |
Vue de comparaison
Pour rechercher les objets fuites, comparez plusieurs instantanés les uns aux autres. Dans une application web, en règle générale, l’exécution d’une action, puis l’action inverse ne doit pas conduire à davantage d’objets en mémoire. Par exemple, lors de l’ouverture d’un document, puis de sa fermeture, le nombre d’objets en mémoire doit être le même qu’avant l’ouverture du document.
Pour vérifier que certaines opérations ne créent pas de fuites :
Prenez un tas instantané avant d’effectuer une opération.
Effectuez l’opération. Autrement dit, interagissez avec la page d’une manière ou d’une autre, ce qui peut provoquer une fuite.
Effectuez l’opération inverse. Autrement dit, faites l’interaction inverse et répétez-la plusieurs fois.
Prenez un deuxième tas instantané.
Dans le deuxième segment de mémoire instantané, remplacez l’affichage par Comparaison, en le comparant à l’instantané 1.
Dans la vue Comparaison , la différence entre deux instantanés s’affiche :
Lorsque vous développez un constructeur dans la liste, les instances d’objet ajoutées et supprimées s’affichent.
Affichage contenant-contenu
La vue Contenant-contenu vous permet d’examiner les fermetures de fonctions, d’observer les objets internes de machine virtuelle qui composent vos objets JavaScript et de comprendre la quantité de mémoire utilisée par votre application à un niveau très bas :
La vue Contenant-contenu affiche les types d’objets suivants :
Points d’entrée de la vue d’endiguement | Description |
---|---|
Objets DOMWindow | Objets globaux pour le code JavaScript. |
Racines du GC | Racines GC utilisées par le garbage collector de la machine virtuelle JavaScript. Les racines gc sont composées de mappages d’objets intégrés, de tables de symboles, de piles de threads de machine virtuelle, de caches de compilation, d’étendues de handle et de handles globaux. |
Objets natifs | Objets créés par le navigateur, tels que les nœuds DOM et les règles CSS, qui sont affichés dans la machine virtuelle JavaScript pour autoriser l’automatisation. |
La section Retainers
La section Retainers s’affiche en bas de l’outil Mémoire et affiche tous les objets qui pointent vers l’objet sélectionné. La section Retainers est mise à jour lorsque vous sélectionnez un autre objet dans la vue Résumé, Contenant-contenu ou Comparaison .
Dans la capture d’écran suivante, un objet chaîne a été sélectionné dans la vue Résumé, et la section Retainers montre que la chaîne est conservée par la x
propriété d’un instance de la Item
classe, qui se trouve dans le example-03.js
fichier :
Masquer les cycles
Dans la section Retainers , lorsque vous analysez les objets qui conservent l’objet sélectionné, vous pouvez rencontrer des cycles. Des cycles se produisent lorsque le même objet apparaît plusieurs fois dans le chemin de rétention de l’objet sélectionné. Dans la section Retainers , un objet cycle est indiqué par grisé.
Pour simplifier le chemin de rétention, masquez les cycles dans la section Rétentions en cliquant sur le menu déroulant Filtrer les arêtes , puis en sélectionnant Masquer les cycles :
Masquer les nœuds internes
Les nœuds internes sont des objets spécifiques à V8 (moteur JavaScript dans Microsoft Edge).
Pour masquer les nœuds internes dans la section Rétentions , dans le menu déroulant Filtrer les arêtes , sélectionnez Masquer l’interne.
Filtrer les instantanés de tas par types de nœuds
Utilisez des filtres pour vous concentrer sur des parties spécifiques d’un tas instantané. Lorsque vous examinez tous les objets d’un tas instantané dans l’outil Mémoire, il peut être difficile de se concentrer sur des objets spécifiques ou de conserver des chemins d’accès.
Pour vous concentrer uniquement sur des types de nœuds spécifiques, utilisez le filtre Types de nœuds, en haut à droite. Par exemple, pour voir uniquement les tableaux et les objets de chaîne dans le tas instantané :
Pour ouvrir le filtre Types de nœuds , cliquez sur Par défaut dans le coin supérieur droit.
Sélectionnez les entrées Tableau et Chaîne .
Le tas instantané est mis à jour pour afficher uniquement les objets de tableau et de chaîne :
Rechercher un objet spécifique
Pour rechercher un objet dans le tas collecté, vous pouvez effectuer une recherche à l’aide de Ctrl+F et donner l’ID de l’objet.
Découvrir les fuites DOM
L’outil Mémoire peut afficher les dépendances bidirectionnelles qui existent parfois entre les objets natifs du navigateur (nœuds DOM, règles CSS) et les objets JavaScript. Cela permet de détecter les fuites de mémoire qui se produisent en raison de nœuds DOM oubliés et détachés qui restent en mémoire.
Pour les éléments détachés, consultez également Rechercher les fuites de mémoire de l’arborescence DOM (« Segment de mémoire instantané » de type > détaché), ci-dessous.
Considérez l’arborescence DOM suivante :
L’exemple de code suivant crée les variables treeRef
JavaScript et leafRef
, qui référencent deux des nœuds DOM dans l’arborescence :
// Get a reference to the #tree element.
const treeRef = document.querySelector("#tree");
// Get a reference to the #leaf element,
// which is a descendant of the #tree element.
const leafRef = document.querySelector("#leaf");
Dans l’exemple de code suivant, l’élément <div id="tree">
est supprimé de l’arborescence DOM :
// Remove the #tree element from the DOM.
document.body.removeChild(treeRef);
L’élément <div id="tree">
ne peut pas être récupéré par la mémoire, car la variable treeRef
JavaScript existe toujours. La treeRef
variable fait directement référence à l’élément <div id="tree">
. Dans l’exemple de code suivant, la treeRef
variable est nullifiée :
// Remove the treeRef variable.
treeRef = null;
L’élément <div id="tree">
ne peut toujours pas être récupéré par la mémoire, car la variable leafRef
JavaScript existe toujours. La leafRef.parentNode
propriété fait référence à l’élément <div id="tree">
. Dans l’exemple de code suivant, la leafRef
variable est nullifiée :
// Remove the leafRef variable.
leafRef = null;
À ce stade, l’élément <div id="tree">
peut être récupéré par la mémoire.
leafRef
Et treeRef
doivent d’abord être nullifiés, pour que l’arborescence DOM entière sous l’élément <div id="tree">
soit récupérée par la mémoire.
Page web de démonstration : Exemple 6 : Fuite de nœuds DOM
Pour comprendre où les nœuds DOM peuvent fuir et comment détecter une telle fuite, ouvrez l’exemple de page web Exemple 6 : Fuite de nœuds DOM dans une nouvelle fenêtre ou un nouvel onglet.
Page web de démonstration : Exemple 9 : Fuites DOM plus importantes que prévu
Pour voir pourquoi une fuite DOM peut être plus grande que prévu, ouvrez l’exemple de page web Exemple 9 : Fuites DOM plus grandes que prévu dans une nouvelle fenêtre ou un nouvel onglet.
Analyser l’impact des fermetures sur la mémoire
Pour analyser l’impact des fermetures sur la mémoire, essayez cet exemple :
Ouvrez la page web de démonstration Eval is evil dans une nouvelle fenêtre ou un nouvel onglet.
Enregistrer un tas instantané.
Dans la page web rendue, cliquez sur le bouton Fermetures avec eval .
Enregistrez un deuxième tas instantané.
Dans la barre latérale, le nombre sous la deuxième instantané doit être supérieur au nombre situé sous la première instantané. Cela indique que la page web utilise davantage de mémoire après avoir cliqué sur le bouton Fermetures avec eval .
Dans le deuxième instantané de tas, remplacez l’affichage par Comparaison, puis comparez le deuxième tas instantané au premier instantané.
La vue Comparaison montre que de nouvelles chaînes ont été créées dans le deuxième tas instantané :
Dans la vue Comparaison, développez le constructeur (chaîne).
Cliquez sur la première entrée (chaîne).
La section Retainers est mise à jour et indique que la
largeStr
variable conserve la chaîne sélectionnée dans la vue Comparaison .L’entrée
largeStr
est automatiquement développée et indique que la variable est conservée par laeC
fonction, qui est la fermeture où la variable est définie :
Conseil : fonctions de nom pour différencier les fermetures d’un instantané
Pour faire facilement la distinction entre les fermetures JavaScript dans un tas instantané, donnez des noms à vos fonctions.
L’exemple suivant utilise une fonction sans nom pour retourner la largeStr
variable :
function createLargeClosure() {
const largeStr = 'x'.repeat(1000000).toLowerCase();
// This function is unnamed.
const lC = function() {
return largeStr;
};
return lC;
}
L’exemple suivant nomme la fonction, ce qui facilite la distinction entre les fermetures dans le tas instantané :
function createLargeClosure() {
const largeStr = 'x'.repeat(1000000).toLowerCase();
// This function is named.
const lC = function lC() {
return largeStr;
};
return lC;
}
Enregistrer et exporter des chaînes à partir d’un tas instantané vers JSON
Lorsque vous prenez un tas instantané dans l’outil Mémoire, vous pouvez exporter tous les objets de chaîne du instantané vers un fichier JSON. Dans l’outil Mémoire , dans la section Constructeur , cliquez sur le bouton Enregistrer tout dans le fichier en regard de l’entrée (string)
:
L’outil Mémoire exporte un fichier JSON qui contient tous les objets de chaîne du tas instantané :
Rechercher les fuites de mémoire de l’arborescence DOM (type > de profilage « Tas instantané détaché »)
Une façon de rechercher et d’afficher tous les éléments détachés sur une page web consiste à utiliser le type de profilage Tas instantané de l’outil Mémoire, puis à taper Détaché dans la zone de texte Filtrer par classe, comme suit. Voir aussi Outils pour examiner les éléments détachés dans Résoudre les problèmes de mémoire.
Le code suivant produit des nœuds DOM détachés :
var detachedTree;
function create() {
var ul = document.createElement('ul');
for (var i = 0; i < 10; i++) {
var li = document.createElement('li');
ul.appendChild(li);
}
detachedTree = ul;
}
document.getElementById('create').addEventListener('click', create);
Ce code crée un ul
nœud avec dix li
enfants. Les nœuds sont référencés par le code, mais ils n’existent pas dans l’arborescence DOM, de sorte que chaque nœud est détaché.
Les instantanés de tas sont un moyen d’identifier les nœuds détachés. Un tas instantané montre comment la mémoire est distribuée entre les objets JS et les nœuds DOM de votre page au moment de l’instantané.
Utiliser le type de profilage « Heap instantané » pour rechercher des éléments détachés
Pour utiliser le tas instantané type de profilage pour rechercher des éléments détachés :
Ouvrez une page web, telle que la page web de démonstration Éléments détachés, dans une nouvelle fenêtre ou un nouvel onglet.
Cliquez avec le bouton droit sur la page web, puis sélectionnez Inspecter. Vous pouvez également appuyer sur Ctrl+Maj+I (Windows, Linux) ou Cmd+Option+I (macOS).
DevTools s’ouvre.
Dans DevTools, dans la barre d’activité, sélectionnez l’outil Mémoire ().
Si cet onglet n’est pas visible, cliquez sur le bouton Autres outils (), puis sélectionnez Mémoire. L’outil Mémoire s’ouvre :
Si le bouton d’option Tas instantané n’est pas affiché, car un profil est déjà affiché, dans le coin supérieur gauche, cliquez sur Profils ().
Vous n’avez pas besoin de sélectionner le bouton d’option Heap instantané à ce stade, car la page web n’a pas encore généré d’éléments détachés.
Générez des messages, qui seront stockés par le instance JavaScript de la classe Room :
Dans la page web de démonstration, cliquez sur le bouton Trafic rapide .
La page web de démonstration commence à générer des messages et à les afficher dans la page web :
Une fois que certains messages sont affichés, cliquez sur le bouton Arrêter dans la page web de démonstration.
Chaque message est un
<div class="message">
élément référencé par le instance Room 1 de laRoom
classe . Il n’y a aucun élément détaché dans l’arborescence DOM de la page web, car tous les éléments de message sont attachés au présent, Salle 1 instance de la classe Room.Remplacez par un autre instance de la classe Room, afin que les éléments soient détachés :
Dans la page web de démonstration, cliquez sur le bouton Salle 2, qui correspond à un autre instance de la
Room
classe.Dans la page web, les messages disparaissent :
Les messages générés pour la salle 1 instance de la classe Room (
<div class="message">
éléments) ne sont plus attachés au DOM, mais ils sont toujours référencés par le instance room 1 de la classe Room. Il s’agit d’éléments détachés, ce qui peut entraîner des fuites de mémoire, sauf s’ils vont être réutilisés par la page web.Obtenez la liste des éléments détachés :
Dans DevTools, dans l’outil Mémoire , cliquez sur l’icône Collecter la mémoire ( :
Le navigateur exécute le garbage collection, en supprimant tous les nœuds qui ne sont plus référencés par un objet JavaScript.
Dans l’outil Mémoire, sélectionnez le bouton d’option Tas instantané.
Cliquez sur le bouton Prendre instantané en bas de l’outil Mémoire.
Le instantané est traité, chargé, puis répertorié dans la barre latérale Profils, dans la section Instantanés du tas.
Dans la zone de texte Filtrer par classe , tapez détaché :
Les éléments DOM détachés qui ne peuvent pas être collectés par la mémoire sont affichés.
Identifiez le code JavaScript qui fait référence à un élément détaché particulier :
Dans le tas instantané, développez un objet Detached, tel que Detached <div>, puis sélectionnez un nœud div détaché <class="message ».>
Les informations sont affichées dans le volet Rétention en bas de l’outil Mémoire .
Dans le volet Rétentions , cliquez sur le
room.js:13
lien d’un élément non monté dans Salle sous Tableau. L’outil Sources s’ouvre, affichantroom.js
, fait défiler jusqu’à la ligne 13 :Pour inspecter la fuite de mémoire possible, étudiez le code qui utilise le
unmounted
tableau et assurez-vous que la référence au nœud est supprimée lorsqu’il n’est plus nécessaire.Pour revenir à l’outil Mémoire , dans la barre d’adresses, sélectionnez l’outil Mémoire .
Pour obtenir d’autres façons d’afficher les éléments détachés, consultez Outils d’examen des éléments détachés dans Résoudre les problèmes de mémoire.
Voir aussi
- Outils permettant d’examiner les éléments détachés dans Résoudre les problèmes de mémoire.
- Terminologie de la mémoire
Externe:
- Recherche et débogage des fuites de mémoire dans JavaScript avec Chrome DevTools - jeu de diapositives (par Gonzalo Ruiz de Villa), qui s’applique également à Microsoft Edge DevTools.
Remarque
Les parties de cette page sont des modifications basées sur le travail créé et partagé par Google et utilisées conformément aux termes décrits dans la licence internationale Creative Commons Attribution 4.0. La page originale se trouve ici et est créée par Meggin Kearney.
Cette œuvre est concédée sous licence creative commons attribution 4.0 international.