memoria liberar how collector javascript memory-leaks browser circular-reference

liberar - how to free memory javascript



javascript, referencias circulares y pérdidas de memoria (3)

Por lo que recuerdo de un pasado no muy lejano, los intérpretes de Javascript sufrieron problemas de pérdida de memoria cuando se enfrentaron con referencias circulares.

¿Sigue siendo así en los últimos navegadores? (por ejemplo, Chrome, FF 3.5, etc.)



La gran mayoría de las filtraciones de las que hablamos con JavaScript se encuentran específicamente en IE6-7 cuando se crea un bucle de referencia entre los objetos JavaScript y los objetos host como los nodos DOM.

En IE6 esto es particularmente pernicioso en el sentido de que no recuperas la memoria cuando sales de la página; se ha ido hasta que salgas del navegador. En IE7, borrar la página ahora devuelve la memoria, pero aún puede tener dificultades cuando tiene una aplicación de larga ejecución. IE8 soluciona la mayor parte de este problema de manera adecuada convirtiendo los nodos DOM en objetos JavaScript nativos en lugar de objetos host. (Todavía podría desencadenar las filtraciones en IE8 al incluir otros objetos no nativos como objetos ActiveX en un bucle de referencia).

Seguramente todavía habrá pequeñas y oscuras pérdidas de memoria al acecho en lugares aleatorios para todos los navegadores, especialmente en versiones anteriores. Pero no hay una sola forma de categorizar fácilmente y evitarlos como con el problema de reintroducción de IE.


Para agregar a la respuesta bobince , hice algunas pruebas con IE8 .

Intenté casi todos los ejemplos proporcionados en http://www.javascriptkit.com/javatutors/closuresleak/index.shtml

Ninguno de ellos está perdiendo memoria (al menos no de manera perceptible), excepto en el ejemplo que elimina los nodos secundarios con eventos todavía adjuntos .

Este tipo de ejemplo, creo que es mejor explicado por Douglas Crockford en su queuetest2.

Este todavía pierde memoria en IE8 y es bastante fácil de probar simplemente ejecutando el script de prueba y mirando el Administrador de tareas de Windows - Rendimiento - Uso de PF. Verás que el uso de PF aumenta en casi 1 MB por ciclo (muy rápido).

Pero en IE8 la memoria se libera en la descarga de la página (como navegar a una página nueva o volver a cargar la misma página ) y obviamente también cuando se cierra por completo el navegador.

Entonces, para que un usuario final perciba que esta memoria se filtra en IE8 (como rendimiento systerm reducido), necesita permanecer en la misma página durante mucho tiempo, lo que en estos días puede ocurrir con AJAX, pero esta página también necesita hacer cientos de childnodes eliminación de elementos con evento adjunto a ellos .

La prueba de Douglas Crockford está haciendo hincapié en el navegador con 10000 nodos añadidos y luego eliminado , eso es excelente para mostrarle el problema, pero en la vida real nunca tuve una página que eliminara más de 10 elementos. Normalmente, INMHO es más rápido de usar display: none lugar de eliminar un conjunto completo de nodos, es por eso que no uso tanto removeChild .

Para quien esté más interesado en la fuga de memoria IE8 explicada anteriormente, hice otra prueba y parece que las pérdidas de mem no aparecen en IE8 cuando se utiliza innerHTML en lugar de appendChild/removeChild para agregar / eliminar elementos secundarios con eventos adjuntos. Así que aparentemente la función de purga de Douglas Crockford (sugerida por él para evitar fugas de memoria en IE) ya no es necesaria en IE8 al menos cuando se usa innerHTML ...

( EDITADO gracias al comentario 4esn0k más abajo ) ... además, la función de purga de Douglas Crockford NO funciona en IE8, en su código var a = d.attributes devuelve ningún atributo onclick (ni ningún otro atributo de onevent ) que se haya agregado en el tiempo de ejecución IE8 (se devuelven en IE7).

Douglas Crockford dice:

"La función de purga debe invocarse antes de eliminar cualquier elemento, ya sea mediante el método removeChild o estableciendo la propiedad innerHTML ".

Proporciono aquí el código para la prueba:

<body> <p>queuetest2 similar to the one provided by Douglas Crockford at http://www.crockford.com/javascript/memory/leak.html <br>but this one adds/removes spans using innerHTML instead of appendChild/removeChild.</p> <div id="test"></div> <script> /* ORIGINAL queuetest2 CODE FROM DOUGLAS CROCKFORD IS HERE http://www.crockford.com/javascript/memory/queuetest2.html */ (function (limit, delay) { var n = 0; var add = true; function makeSpan(n) { var div = document.getElementById(''test''); //adding also an inline event to stress more the browser div.innerHTML = "<span onmouseover=/"this.style.color = ''#00ff00'';/">" + n + "</span>"; var s = div.getElementsByTagName(''span'')[0]; s.onclick = function(e) { s.style.backgroundColor = ''red''; alert(n); }; return s; } function process(n) { if(add) s = makeSpan(n); else s.parentNode.innerHTML = ""; //removing span by clearing the div innerHTML add = !add; } function loop() { if (n < limit) { process(n); n += 1; setTimeout(loop, delay); } } loop(); })(10000, 10); </script> </body>