Juste rencontré un client qui ont d'énormes problèmes de fuite de mémoire dans leur webapp Ajax. J'ai donc décidé de créer le testcase suivant pour démontrer le problème:Ajout d'éléments DOM avec jquery append() semble fuir la mémoire?
J'ai utilisé goutte à goutte/Sieve pour le profilage de la mémoire dans l'exemple ci-dessous (http://home.orange.nl/jsrosman/)
Le cas est simple: je le javascript suivant:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js">
</script>
</head>
<script type="text/javascript">
var lihtml = "<li class='green'>this is a test text</li>";
function populatelist() {
for (var i = 0; i < 10000; i++) {
$('#listparent').append(lihtml);
}
}
function clearlist() {
$('#listparent').empty();
if (typeof (CollectGarbage) == "function") {
alert('gc');
CollectGarbage();
}
}
/* Alternative clearlist with Remove instead of Empty(), still leaks */
function clearlist() {
/* test remove the parent itself instead of empty below */
$('#listparent').remove();
$('body').append("<ul id='listparent'>");
//$('#listparent').empty();
if (typeof (CollectGarbage) == "function") {
alert('gc');
CollectGarbage();
}
}
/* Edit!, this is the most effective way to release memory so far */
function clearlist() {
$('#listparent').html("");
if (typeof (CollectGarbage) == "function") {
alert('gc');
CollectGarbage();
}
}
</html>
</script>
<body>
<button onclick="javascript:populatelist()">Populate list</button>
<button onclick="javascript:clearlist()">Clear list</button>
<ul id="listparent">
<li>kjjk</li>
</ul>
</body>
</html>
Chaque clic sur la liste populate 10000 éléments ajoute li (représenté sous forme de texte). Clearlist appelle jquery empty() qui devrait supprimer le sous-arbre DOM et le rendre éligible pour GC. Donc, je lance ce cas dans sIEve et pour chaque fois que j'ajoute de nouveaux éléments, l'utilisation de la mémoire augmente, je ne l'ai jamais vu garbage collecter ou libérer de la mémoire. Pas même lorsque l'utilisation de la RAM atteint 1,5 Go et même si j'essaie d'appeler GC explicitement pour IE.
C'est le même symptôme que j'ai vu chez le client qui a utilisé Jquery Ajax pour les données de la liste au lieu de mon contenu statique obv. Est-ce que je crée le DOM dans le mauvais sens?
Quelqu'un peut-il me dire pourquoi ce n'est pas ramassé, je ne vois pas d'autres références aux éléments DOM pour savoir pourquoi ils ne devraient pas être collectés. Un autre comportement bizarre est que parfois, dans l'utilisation de la mémoire sIEve, augmente même lorsque je clique sur la liste vide (quand la méthode jquery empty() est appelée)?
Si quelqu'un a une entrée, je serais très heureux. UPDATE, j'ai essayé d'utiliser $ ('# listparent'). Html ("") à la place qui semble libérer le DOM correctement, au moins il est publié dans sIEve. Je suppose que c'est la meilleure solution jusqu'à maintenant, mais je n'ai aucune explication à pourquoi remove() et empty() ne semble pas fonctionner. Peut-être qu'ils ne fonctionnent que pour les éléments ajoutés statiquement?
juste curieux, avez-vous essayé dans plusieurs navigateurs? – Prescott
Aucun sIEve ne fonctionne que dans IE, n'ont pas essayé FFX, principalement parce que IE est le seul navigateur utilisé par les utilisateurs dans ce système. – user408346
En fait $ ('# listparent').html (""); fonctionne beaucoup mieux que vide() et remove() et semble libérer tout le DOM. Je suis sans voix – user408346