2010-03-15 21 views
63

Esta es una especie de seguimiento a una pregunta que he publicado la semana pasada: Simple jQuery Ajax call leaks memory in Internet Explorer¿Por qué jquery pierde memoria tan mal?

Me encanta la sintaxis de jQuery y todas sus buenas características, pero he tenido problemas con una página que se actualiza automáticamente mesa las células a través de ajax llaman filtración de memoria.

Así que creé dos páginas de prueba simples para experimentar. Ambas páginas hacen una llamada ajax cada .1 segundos. Después de cada llamada ajax exitosa, se incrementa un contador y se actualiza el DOM. La secuencia de comandos se detiene después de 1000 ciclos.

Uno usa jquery para la llamada ajax y para actualizar el DOM. El otro usa la API de Yahoo para el ajax y hace un document.getElementById (...). InnerHTML para actualizar el DOM.

La versión de jquery pierde mal la memoria. Corriendo en goteo (en XP Home con IE7), comienza en 9MB y termina en aproximadamente 48MB, con la memoria creciendo linealmente todo el tiempo. Si hago un comentario sobre la línea que actualiza el DOM, aún termina en 32MB, sugiriendo que incluso las simples actualizaciones de DOM pierden una cantidad significativa de memoria. La versión sin jquery comienza y finaliza a aproximadamente 9 MB, independientemente de si actualiza el DOM.

¿Alguien tiene una buena explicación de lo que está causando que jquery gotee tan mal? ¿Me estoy perdiendo algo obvio? ¿Hay alguna referencia circular de la que no tenga conocimiento? ¿O simplemente jquery tiene algunos problemas serios de memoria?

Aquí es la fuente de la que gotea (jQuery) Versión:

<html> 
    <head> 
    <script type="text/javascript" src="http://www.google.com/jsapi"></script> 
    <script type="text/javascript"> 
     google.load('jquery', '1.4.2'); 
    </script> 
    <script type="text/javascript"> 
     var counter = 0; 
     leakTest(); 
     function leakTest() { 
     $.ajax({ url: '/html/delme.x', 
       type: 'GET', 
       success: incrementCounter 
       }); 
     } 
     function incrementCounter(data) { 
     if (counter<1000) { 
      counter++; 
      $('#counter').text(counter); 
      setTimeout(leakTest,100); 
     } 
     else $('#counter').text('finished.'); 
     } 
    </script> 
    </head> 
    <body> 
    <div>Why is memory usage going up?</div> 
    <div id="counter"></div> 
    </body> 
</html> 

Y aquí es la versión no gotea:

<html> 
    <head> 
    <script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/yahoo/yahoo-min.js"></script> 
    <script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/event/event-min.js"></script> 
    <script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/connection/connection_core-min.js"></script> 
    <script type="text/javascript"> 
     var counter = 0; 
     leakTest(); 
     function leakTest() { 
     YAHOO.util.Connect.asyncRequest('GET', 
             '/html/delme.x', 
             {success:incrementCounter}); 
     } 
     function incrementCounter(o) { 
     if (counter<1000) { 
      counter++; 
      document.getElementById('counter').innerHTML = counter; 
      setTimeout(leakTest,100); 
     } 
     else document.getElementById('counter').innerHTML = 'finished.' 
     } 
    </script> 
    </head> 
    <body> 
    <div>Memory usage is stable, right?</div> 
    <div id="counter"></div> 
    </body> 
</html> 
+2

¿Qué versión de jquery estás usando? –

+2

¿Sucede en Firefox? – SLaks

+1

Sus fragmentos están cargando 1.4.2 –

Respuesta

8

Mi idea inicial sería que tiene algo que ver con la forma en que el método jquery ajax:

a. crea referencias circulares, especialmente malo para IE

b. crea propiedades en objetos internos que no se pueden eliminar debido a la forma en que se crearon y la configuración de la propiedad DontDelete. Consulte esto para obtener más información: http://perfectionkills.com/understanding-delete/

De cualquier manera, se evitaría que el recolector de basura recogiera la basura, lo que provocaría una fuga de memoria descontrolada, especialmente si la función sospechosa se ejecuta con frecuencia.

+0

Esta situación también puede ocurrir dentro de aplicaciones de nodos, principalmente debido al uso de variables declaradas en un ámbito de función principal, que se utiliza en un cierre de devolución de llamada más tarde. Esto se puede evitar desreferenciando los objetos después de su uso: http://stackoverflow.com/questions/5733665/how-to-prevent-memory-leaks-in-node-js – Alex

Cuestiones relacionadas