2010-03-15 26 views
63

Questa è una specie di un follow-up a una domanda ho inviato la settimana scorsa: Simple jQuery Ajax call leaks memory in Internet ExplorerPerché jquery perde memoria così male?

amo la sintassi jQuery e tutte le sue caratteristiche molto interessanti, ma ho avuto problemi con una pagina che si aggiorna automaticamente da tavolo le celle via ajax chiamano la perdita di memoria.

Così ho creato due semplici pagine di test per sperimentare. Entrambe le pagine eseguono una chiamata ajax ogni .1 secondi. Dopo ogni chiamata ajax, un contatore viene incrementato e il DOM viene aggiornato. Lo script si interrompe dopo 1000 cicli.

Uno utilizza jquery sia per la chiamata ajax che per aggiornare il DOM. L'altro utilizza l'API di Yahoo per l'ajax e fa un documento.getElementById (...). InnerHTML per aggiornare il DOM.

La versione jquery perde la memoria. Running in drip (su XP Home con IE7), inizia a 9 MB e termina a circa 48 MB, con una memoria che cresce linearmente per tutto il tempo. Se commento la riga che aggiorna il DOM, termina ancora a 32 MB, suggerendo che anche gli aggiornamenti DOM semplici perdono una quantità significativa di memoria. La versione non jquery inizia e termina a circa 9 MB, indipendentemente dal fatto che aggiorni il DOM.

Qualcuno ha una buona spiegazione di ciò che sta causando perdite jquery così male? Mi manca qualcosa di ovvio? C'è un riferimento circolare di cui non sono a conoscenza? Oppure jquery ha solo dei seri problemi di memoria?

Qui è la sorgente per la versione che perde (jQuery):

<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> 

E qui è la versione non perde:

<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

Quale versione di jquery stai usando? –

+2

Accade in Firefox? – SLaks

+1

I suoi frammenti caricano 1.4.2 –

risposta

8

Il mio primo pensiero è che ha qualcosa a che fare con il metodo jquery ajax:

a. crea riferimenti circolari, particolarmente negativi per IE

b. crea proprietà su oggetti interni che non possono essere cancellati a causa del modo in cui sono stati creati e dell'impostazione della proprietà DontDelete. Vedere questo per maggiori informazioni: http://perfectionkills.com/understanding-delete/

In entrambi i casi, il garbage collector non sarebbe in grado di raccogliere la spazzatura, il che si tradurrebbe in una fuga di memoria in fuga, soprattutto se la funzione sospetta viene eseguita frequentemente.

+0

Questa situazione può verificarsi anche all'interno delle applicazioni del nodo, principalmente a causa dell'uso di variabili dichiarate nell'ambito di una funzione genitore, utilizzate successivamente in una chiusura di callback. Questo può essere evitato de-referenziando gli oggetti dopo l'uso: http://stackoverflow.com/questions/5733665/how-to-prevent-memory-leaks-in-node-js – Alex

Problemi correlati