Localisation de la fuite de mémoire DOM détachée

J'ai eu du mal à diagnostiquer une fuite de mémoire d'arbre DOM détachée dans une très grande application web d'une seule page, créée principalement avec Knockout.

J'ai modifié l'application pour attacher un objet FooBar fictif à un élément de bouton HTML particulier qui devrait être récupéré lorsque l'utilisateur passe à une «page» différente de l'application. En utilisant la fonction d' instantané de tas de Chrome, je peux voir qu'une ancienne instance FooBar (qui aurait dû être GC'ed) est toujours accessible depuis son HTMLButtonElement dans un (grand) arbre DOM détaché.

Traçant les références via le panneau d' arborescence de retenue , je suis la chaîne qui prend une distance décroissante de la racine du GC. Cependant, à un certain point, ma recherche atteint une impasse à une distance de noeud 4 de la racine (dans ce cas)! L'arbre de retenue ne répertorie aucune référence à ce noeud, mais sait en quelque sorte qu'il se trouve à quatre étapes de la racine du GC.

Voici la partie de l'arbre de retenue qui m'a perplexe (les nombres à droite sont des distances de la racine):

 v foobar in HTMLButtonElement 10 v [4928] in Detached DOM tree / 5643 entries 9 v native in HTMLOptionElement 8 v [0] in Array 7 v mappedNodes 6 v [870] in Array 5 v itemsToProcess in system / Context 4 context in function itemMovedOrRetained() context in function callCallback() 

L'arbre de retenue ne montre pas les références ici à la distance 3 ou supérieure.

Quelqu'un peut-il m'expliquer cela? J'espérais pouvoir suivre la chaîne de référence vers la partie offensante du code de l'application JavaScript, mais cela a été bloqué!

Tout d'abord – n'utilisez pas la delete comme l'un des commentaires suggérés. Définir une référence à null est le bon moyen de disposer des choses. delete brise la "classe cachée". Pour le voir vous-même, exécutez mes exemples à partir de https://github.com/naugtur/js-memory-demo

Rafe, le contenu que vous voyez dans profiler est souvent difficile à comprendre. Le bit que vous avez posté ici semble étrange et pourrait être un bug ou une fuite de mémoire en dehors de votre application (les navigateurs fuient aussi), mais sans exécuter votre application, il est difficile de le dire. Votre arbre de retenue se termine dans un contexte de fonction et il peut être retenu par une référence à cette fonction ou à une autre fonction partageant le contexte. Il est peut-être trop compliqué pour le profileur de le visualiser correctement.

Je peux vous aider à identifier le problème.

Tout d'abord, passez à l'onglet Chronologie dans les décontames et utilisez-le pour observer le moment où votre fuite se produit. Sélectionnez uniquement l'allocation de mémoire et commencez l'enregistrement. Passez par un scénario que vous prévoyez de fuir. Les barres qui restent bleues sont les fuites. Vous pouvez sélectionner leur environnement dans la ligne de temps et se concentrer sur leur arbre de retenue. Les éléments les plus intéressants dans les arbres dom isolés sont les rouges – ils sont référencés de l'extérieur. Le reste est conservé car n'importe quel élément d'un arbre est référencé, il a des références à tout le reste ( x.parentNode )

Si vous avez besoin de plus de détails, vous pouvez prendre plusieurs instantanés dans le profiler, afin que vous ayez un instantané avant et après la cause de la fuite (que vous avez trouvée avec le calendrier – vous connaissez maintenant l'action exacte qui l'entraîne). Vous pouvez ensuite comparer ceux du profileur – il y a une vue "comparer". Qui est plus compréhensible que d'autres.

Vous pouvez également enregistrer vos instantanés de tas du profiler et les publier en ligne, afin que nous puissions jeter un oeil. Il y a un lien de sauvegarde sur chacun d'eux dans la liste à gauche.


Le profilage de la mémoire est difficile et nécessite une certaine pratique et compréhension des outils. Vous pouvez pratiquer quelques exemples de mon exposé:

http://naugtur.pl/pres/mem.html#/5/2

Mais le véritable guide complet pour utiliser le profiler de mémoire est ce document:

https://developer.chrome.com/devtools/docs/javascript-memory-profiling#looking_up_color_coding

Lien mis à jour: https://developers.google.com/web/tools/profile-performance/memory-problems/memory-diagnosis