40 votes

Recherche de fuite de mémoire JS dans les outils de développement chromés

Je suis en utilisant google chrome dev tools de travailler si il y a une fuite de mémoire dans certains code JS. La chronologie de la mémoire semble bon avec de la mémoire récupérée comme prévu.

enter image description here

Cependant, l' instantané de la mémoire est une source de confusion, car il semble comme il y a une fuite, car il y a des entrées au titre de "Détaché Arborescence DOM".

C'est la matière en vertu de l' "Détaché Arborescence DOM" qui attend d'être nettoyée ou sont ces vraies fuites?

Aussi personne ne sait comment faire pour savoir quelle fonction est maintenant sur une référence à un élément détaché?

enter image description here

34voto

Esailija Points 74052

Ces éléments sont référencés dans votre code, mais ils sont déconnectés de la page principal de l'arborescence DOM.

Exemple Simple:

var a = document.createElement("div");

a références à la déconnexion d'un élément de maintenant, il ne peut pas être GC avais quand a est toujours dans la portée.

Si le détachement dom arbres restent en mémoire, alors vous êtes en gardant des références. C'est un peu facile avec jQuery pour ce faire, il suffit d'enregistrer une référence à une traversée de résultat et de le garder autour. Par exemple:

var parents = $("span").parent("div");
$("span").remove();

Maintenant, les travées sont référencés même si elle n'apparaît pas, vous faites référence à eux de toute façon. parents indirectement conserve une référence pour tous les travées grâce à jQuery .prevObject de la propriété. Ce faisant, parents.prevObject serait donner à l'objet qui référence tous les travées.

Voir l'exemple ici http://jsfiddle.net/C5xCR/6/. Même si elle n'est pas directement apparaît que les travées être référencé, ils sont, en fait, référencé par l' parents variable globale et vous pouvez voir les 1000 s'étend dans le Détaché arborescence DOM ne jamais s'en aller.

Voici maintenant le même jsfiddle, mais avec:

delete parents.prevObject

Et vous pouvez voir les travées sont plus dans le détachée arborescence dom, ou n'importe où ailleurs. http://jsfiddle.net/C5xCR/7/

15voto

Yury Semikhatsky Points 861

C'est la matière en vertu de l' "Détaché Arborescence DOM" qui attend d'être nettoyée ou sont ces vraies fuites?

Avant de prendre l'instantané le navigateur va exécuter la collecte des ordures et de balayer tous les objets qui ne sont pas référencées. Si le tas instantané toujours contenir uniquement les objets vivants. En conséquence si un décollement de l'Arborescence du DOM est dans l'instantané qu'il doit y avoir un élément dans l'arbre qui est référencé à partir de JavaScript.

Aussi personne ne sait comment faire pour savoir quelle fonction est maintenant sur une référence à un élément détaché?

Il devrait y avoir un élément(ou plusieurs) dans la même détaché DOM arbre sur fond jaune. Ces éléments sont référencés dans le code JavaScript. Vous pouvez savoir exactement qui maintient la référence à l'élément dans les robinets de retenue de l'arbre.

1voto

Elias Van Ootegem Points 29404

Puisque vous avez ajouté le jQuery balise, j'ai eu une astuce suspicion quant à ce qui est un jQuery chose. Un rapide sur google m'a amené sur cette page. Lors de l'utilisation de jQ l' detach méthode, une référence à l'objet est toujours conservé dans la mémoire, ce qui pourrait être la cause de votre instantané.

Une autre chose peut-être que jQuery a un div nœud à la main, qui est-bien évidemment - de garder en mémoire, mais jamais ajouté au dom... une sorte d' document.createNode('div') sans ajout d'elle. Cela, aussi, se montrer dans l'instantané de la mémoire. Vous ne pouvez pas y échapper, jQuery utilise pour analyser les chaînes dans des éléments html.

Afin de supprimer certains éléments de la mémoire, utiliser le jQuery .remove() méthode, et votre mem sera effacé instantanément.cf Esailija commentaire sur pourquoi est - remove n'est pas tout à fait adapter le projet de loi ici.
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]); Devrait supprimer l'élément tout à fait, mais pourrait ne pas séparer les événements. Peut-être quelque chose le long des lignes de:

$('#someElem').detach();//to remove any event listeners
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);//remove element all together

Et, encore une fois, comme Esailija a souligné, dans sa réponse, assurez-vous d'attribuer les références à tout objet jQuery (var someRef= $('.someSelector');) à une variable globale, comme ils ne seront pas en GC ed. Il suffit d'éviter globals tous ensemble, en fait.
Mais pour répondre à votre question, brièvement et clairement: non ce ne sont pas de vrais fuites de mémoire, la mémoire doit être libéré sur l' onbeforeunload événement. L'objet jQuery est supprimée, de sorte que toutes les références hors de portée. Au moins, c'est ce Que mon "recherche" m'amènent à penser. Peut-être pas tout à fait pertinente, mais seulement comme une référence , Voici une question sur mem-fuites que j'ai posté tout à l'arrière, et avec elle quelques choses que j'ai découvert..

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X