Acabo de reunirme con un cliente que tiene grandes problemas de pérdida de memoria en su aplicación web Ajax. Así que decidí crear el siguiente caso de prueba para demostrar el problema:Al agregar elementos DOM con jquery append(), ¿se pierde la memoria?
he utilizado por goteo/Tamiz para perfiles de memoria en el siguiente ejemplo (http://home.orange.nl/jsrosman/)
El caso es simple: tengo el siguiente javascript:
<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>
Cada clic en Rellenar lista anexa 10000 elementos li (representado como texto). Clearlist llama a jquery empty() que supuestamente debería borrar el subárbol DOM y hacerlo elegible para GC.
Ejecuto este caso en sIEve y cada vez que agrego nuevos elementos aumenta el uso de la memoria, nunca lo he visto recoger basura o memoria libre. Ni siquiera cuando el uso de RAM alcanza 1.5GB y aunque intento llamar a GC explícitamente para IE.
Este es el mismo síntoma que vi en el cliente que usó Jquery Ajax para los datos de la lista en lugar de mi contenido estático obv.
¿Estoy creando el DOM de la manera incorrecta? ¿Alguien puede decirme por qué no es basura recolectada, no puedo ver ninguna otra referencia a los elementos DOM en cuanto a por qué no deberían recogerse basura? Otro comportamiento extraño es que a veces el uso de la memoria de memoria incluso aumenta cuando hago clic en la lista vacía (cuando se llama al método jquery empty()).
Si alguien tiene comentarios, estaría MUY feliz.
ACTUALIZACIÓN, he intentado usar $ ('# listparent'). Html ("") que parece liberar el DOM correctamente, al menos se está liberando en sIEve. Supongo que esa es la mejor solución hasta el momento, aunque no tengo ninguna explicación de por qué eliminar() y vaciar() no parece funcionar. ¿Tal vez solo trabajan para elementos agregados estáticamente?
curiosidad, ¿ha intentado esto en varios navegadores? – Prescott
No sIEve solo funciona en IE, no ha probado FFX, principalmente porque IE es el único navegador utilizado por los usuarios de este sistema. – user408346
En realidad $ ('# listparent').html (""); funciona mucho mejor que empty() y remove() y parece liberar todo el DOM. Estoy sin palabras – user408346