1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
---
title: Vue "Dominants"
slug: Tools/Memory/Dominators_view
translation_of: Tools/Memory/Dominators_view
original_slug: Outils/Memory/Dominators_view
---
<div>{{ToolsSidebar}}</div><div class="geckoVersionNote">
<p>La vue "Dominants" est une des nouveautés de Firefox 46.</p>
</div>
<p>À partir de Firefox 46, l'outil Mémoire inclut une nouvelle vue nommée "Dominants". Celle-ci est utile pour comprendre la "Taille retenue" des objets d'un site : il s'agit de la taille des objets eux-mêmes ainsi que la taille des objets qu'ils gardent en vie par référence.</p>
<p>Si vous n'êtes pas familier avec la "taille de l'objet", la "taille retenue" et les Dominants, il est recommandé de lire l'article sur les <a href="/fr/docs/Tools/Memory/Dominators">concepts des Dominants</a>.</p>
<h2 id="Interface_utilisateur_des_Dominants">Interface utilisateur des Dominants</h2>
<p>Pour afficher la vue des Dominants, il faut sélectionner "Dominants" dans le menu déroulant "Afficher" :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13627/dominators-1.png" style="display: block; height: 230px; margin: 0px auto; width: 800px;"></p>
<p>Cette vue est constituée de deux panneaux:</p>
<ul>
<li>Le panneau de <a href="/fr/docs/Tools/Memory/Dominators_view#Dominators_Tree_panel">l'arbre des Dominants</a> qui affiche quel sont les noeuds de la capture qui retiennent le plus de mémoire.</li>
<li>Le panneau des <a href="/fr/docs/Tools/Memory/Dominators_view#Retaining_Paths_panel">Chemins de rétention</a> (depuis Firefox 47) affiche les 5 plus courts chemins de rétention pour un noeud.</li>
</ul>
<p><img alt="" src="https://mdn.mozillademos.org/files/13629/dominators-2.png" style="display: block; margin: 0px auto;"></p>
<h3 id="Arbre_des_Dominants">Arbre des Dominants</h3>
<p>Ce panneau affiche les objets de la capture qui retiennent le plus de mémoire.</p>
<p>Dans la partie principale de l'UI, la première ligne est nommée "Racines GC". En dessous de cette ligne, il y a une ligne pour :</p>
<ul>
<li>Chaque noeud racine GC. Dans Gecko, il y a plusieurs graph mémoire, et donc plusieurs racines. Il peut y avoir beaucoup de racines (souvent temporaires). Par exemple, les variables allouées sur la stack ont besoin d'être enracinées, les caches internes peuvent eux aussi avoir besoin d'enraciner leurs éléments.</li>
<li>Chaque autre noeud qui est référencé depuis deux racines différentes (vu que dans ce cas, aucune des deux racines ne le domine).</li>
</ul>
<p>Pour chacune de ces lignes, seront affichés :</p>
<ul>
<li>La taille retenue du noeud, en octets et en pourcentage total.</li>
<li>La taille de l'objet du noeud en octets et en pourcentage total.</li>
<li>Le nom du noeud et son adresse mémoire.</li>
</ul>
<p>Les lignes sont classées par la taille de mémoire retenue. Par exemple :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13631/dominators-3.png" style="display: block; height: 228px; margin: 0px auto; width: 700px;"></p>
<p>Dans cette capture d'écran, il est possible de voir qu'il y a cinq linges en dessus de "GC roots". Les deux premiers objets sont "Call" et "Window", et retiennent respectivement 21% et 8% de la mémoire totale de la capture. Il est également possible de voir qu'ils ont une taille (shallow) réduite, donc quasiment toute la mémoire retenue vient d'objets qu'ils dominent.</p>
<p>Juste en dessous de chaque racine GC, tout les noeuds pour lequel cette racine est le <a href="https://developer.mozilla.org/fr/docs/Tools/Memory/Dominators#immediate_dominator">dominant immédiat</a> sont affichés et triés par taille retenue.</p>
<p>Par exemple, cliquer sur le premier objet "Window" affichera ceci :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13633/dominators-4.png" style="display: block; height: 292px; margin: 0px auto; width: 700px;"></p>
<p>Il est possible de voir que "Window" domine un objet "CSS2Properties", dont la taille retenue est de 2ù de la capture. Encore une fois, la taille de l'objet est faible, quasiment toute sa taille retenue est due aux objets dominés. En cliquant sur l'icone en fore de triangle à coté de la fonction, il est possible de voir ces noeuds.</p>
<p>Il est ainsi possible de se faire rapidement une idée de quels objets retiennent le plus de mémoire dans la capture.</p>
<p>Il est possible d'utiliser <kbd>Alt</kbd> + clic pour étendre le graph entier d'un noeud.</p>
<h4 id="Pile_d'allocations">Pile d'allocations</h4>
<p>Dans la barre d'outils, il y a une liste déroulante : "Nommer selon" :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13635/dominators-5.png" style="display: block; height: 224px; margin: 0px auto; width: 800px;"></p>
<p>Par défaut, l'option sélectionnée est "Type". Il est possible de choisir "Call Stack" à la place pour savoir exactement d'ou dans le code les objets sont alloués.</p>
<div class="note">
<p>Cette option est appelée "Allocation Stack" dans Firefox 46.</p>
</div>
<p>Pour l'activer, il faut cocher la case "Enregistrer les piles d'allocations" <em>avant</em> de lancer le coder qui alloue les objets. Il faut ensuite prendre une capture, puis sélectionner "Call Stack" dans le menu déroulant "Nommer selon".</p>
<p>Maintenant, le nom du noeud contient le nom de la fonction qui l'a alloué, ainsi que le fichier, la ligne et la position exacte d'ou dans la fonction l'allocation a été faite. Cliquer sur le nom du fichier ouvrira cette position dans le Débogueur.</p>
<p>{{EmbedYouTube("qTF5wCSD124")}}</p>
<div class="note">
<p>Parfois, une ligne nommée "(no stack available)" est présente. Les piles d'allocations ne sont actuellement enregistrées que pour les objets, pas pour les tableaux, les strings ou les structures internes.</p>
</div>
<h3 id="Chemins_de_rétention">Chemins de rétention</h3>
<div class="geckoVersionNote">Ce panneau est une des nouveautés de Firefox 47.</div>
<p>Ce panneau affiche, pour un noeud sélectionné les 5 plus courts chemins depuis ce noeud jusqu'a une racine GC. Cela permet de voir tous les noeuds qui empêchent ce noeud d'être détruit par le garbage collector (ramasse-miette en <s>bon </s>français). Si un objet est soupçonné de cause une fuite mémoire, ce panneau affichera les objets qui réfrènent l'objet soupçonné.</p>
<p>Pour voir le chemin de rétention, il suffit de sélectionner un noeud dans le panneau de l'arbre des Dominants :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13637/dominators-6.png" style="display: block; height: 415px; margin: 0px auto; width: 800px;"></p>
<p>Ici, un objet a été sélectionné et l'on peut voir un unique chemin jusqu'a la racine GC.</p>
<p>La racine GC <code>Window</code> contient une référence à un objet <code>HTMLDivElement</code>. Cet objet contient lui une référence à un <code>Object</code>, et ainsi de suite. Il est possible de retracer le chemin juste en regardant le panneau de l'arbre des Dominants. Si une seule de ces références venait à être supprimée, les objets en dessous seraient détruits par le garbage collector.</p>
<p>Chaque connexion dans le graph est annoté avec le nom de la variable qui référence l'objet.</p>
<p>Parfois, il y a plus d'un seul chemin de rétention :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13639/dominators-7.png" style="display: block; height: 455px; margin: 0px auto; width: 700px;"></p>
<p>Ici, il y a deux chemins depuis le noeud <code>DocumentPrototype</code> vers la racine GC. Si seulement l'un des des deux venait à être supprimé, le noeud ne serait pas détruit par le garbage collector, puisqu'il serait toujours retenu par l'autre chemin.</p>
<h2 id="Exemple">Exemple</h2>
<p>Pour tester l'outil, il est plus simple d'utiliser un exemple</p>
<p><br>
Nous utiliserons <a href="/fr/docs/Tools/Memory/Monster_example">l'exemple d'allocation de monstres</a>. Cet exemple crée trois tableaux chacun contenant 5000 monstres, chaque monstre possède un nom généré aléatoirement.<br>
</p>
<h3 id="Prendre_une_capture">Prendre une capture</h3>
<p>Pour voir à quoi cela ressemble avec la vue "Dominants", il faut :</p>
<ul>
<li>Charger la page</li>
<li>Activer l'outil Mémoire dans les <a href="/fr/docs/Tools/Tools_Toolbox#Settings">Options</a>, s’il n'est pas encore activé.</li>
<li>Ouvir l'outil Mémoire</li>
<li>Cocher la case " Enregistrer les piles d'allocations"</li>
<li>Appuyer sur le bouton "Make monsters!"</li>
<li>Prendre une capture</li>
<li>Passer à la vue "Dominants"</li>
</ul>
<p>{{EmbedYouTube("HiWnfMoMs2c")}}</p>
<h3 id="Analyse_de_l'arbre_des_dominants">Analyse de l'arbre des dominants</h3>
<p>Les trois tableaux seront les trois premières racines GC, chacun retenant à peu près 23% de la mémoire totale de la capture :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13641/dominators-8.png" style="display: block; height: 165px; margin: 0px auto; width: 700px;"></p>
<p>Étendre un tableau affichera les objets (monstres) qu'il contient. Chaque monstre à une taille réduite de 160 octets. Cette taille inclut les variables int "eye" et "tentacle-count". Chaque monstre à une taille retenue plus grande, car ils retiennent la string utilisée pour stocker le nom du monstre :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13643/dominators-9.png" style="display: block; height: 327px; margin: 0px auto; width: 700px;"></p>
<p>Tout cela se rapproche précisément du <a href="/fr/docs/Tools/Memory/Monster_example#allocation-graph">graph mémoire attendu</a>. Une chose curieuse cependant, où est passé l'objet qui contient ces trois tableaux ? En regardant le chemin de rétention pour un des tableaux, il est possible de le voir :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13645/dominators-10.png" style="display: block; height: 467px; margin: 0px auto; width: 700px;"></p>
<p>Ici, il est possible de voir l'objet retenant le tableau; et même qu'il s'agit du tableau de monstres <code>friendly</code>. Dans la capture d'écran ci-dessus, ce n'est pas visible, cependant ce tableau est aussi enraciné directement à la racine GC. Donc si l'objet arrête de référencer le tableau, celui-ci ne serait toujours pas éligible au garbage collector.</p>
<p>Cela veut dire que l'objet ne domine pas le tableau et donc n'est pas affiché dans l'arbre des Dominants. À voir également, <a href="/fr/docs/Tools/Memory/Dominators#multiple-paths">l'article sur le concept des Dominants.</a></p>
<h3 id="Utiliser_la_vue_Call_Stack">Utiliser la vue Call Stack</h3>
<p>Enfin, il est possible de passer à la vue "Call Stack", afin de voir quels objets sont alloués et de se rendre à ce point dans le Débogueur :</p>
<p>{{EmbedYouTube("qTF5wCSD124")}}</p>
|