2010-03-15 3 views
63

C'est une sorte de suivi à une question que j'ai posté la semaine dernière: Simple jQuery Ajax call leaks memory in Internet ExplorerPourquoi jquery fuit-il si mal la mémoire?

J'adore la syntaxe jquery et toutes ses fonctionnalités intéressantes, mais j'ai eu des problèmes avec une page qui met à jour automatiquement la table cellules via des appels ajax fuite de mémoire. J'ai donc créé deux pages de test simples pour expérimenter. Les deux pages font un appel ajax toutes les .1 secondes. Après chaque appel ajax réussi, un compteur est incrémenté et le DOM est mis à jour. Le script s'arrête après 1000 cycles.

On utilise jquery pour l'appel ajax et pour mettre à jour le DOM. L'autre utilise l'API Yahoo pour l'ajax et fait un document.getElementById (...). InnerHTML pour mettre à jour le DOM.

La version de jquery manque de mémoire. Courant en goutte à goutte (sur XP Home avec IE7), il commence à 9 Mo et se termine à environ 48 Mo, avec une mémoire qui augmente linéairement tout le temps. Si je commente la ligne qui met à jour le DOM, il se termine toujours à 32 Mo, ce qui suggère que même les mises à jour DOM simples fuite d'une quantité importante de mémoire. La version non-jquery démarre et se termine à environ 9 Mo, qu'elle mette à jour le DOM.

Est-ce que quelqu'un a une bonne explication de ce qui cause une fuite si grave? Est-ce que je manque quelque chose d'évident? Y a-t-il une référence circulaire dont je ne suis pas au courant? Ou est-ce que jquery a juste de sérieux problèmes de mémoire?

Voici la source pour la version qui fuit (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> 

Et voici la version non-leaky:

<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

Quelle version de jquery utilisez-vous? –

+2

Cela arrive-t-il dans Firefox? – SLaks

+1

Ses extraits sont en cours de chargement 1.4.2 –

Répondre

8

Ma première pensée serait qu'il a quelque chose à faire avec la méthode jquery ajax soit:

a. crée des références circulaires, particulièrement mauvaises pour IE

b. crée des propriétés sur les objets internes qui ne peuvent pas être supprimés en raison de la manière dont ils ont été créés et du paramètre de la propriété DontDelete. Pour plus d'informations, voir: http://perfectionkills.com/understanding-delete/

De toute façon, le ramasse-miettes ne pourrait pas ramasser la corbeille, ce qui provoquerait une fuite de mémoire, en particulier si cette fonction suspecte s'exécute fréquemment.

+0

Cette situation peut également se produire à l'intérieur des applications de nœud, principalement en raison de l'utilisation de variables déclarées dans une portée de fonction parente, utilisée ultérieurement lors d'une fermeture de rappel. Cela peut être évité en dé-référençant les objets après utilisation: http://stackoverflow.com/questions/5733665/how-to-prevent-memory-leaks-in-node-js – Alex

Questions connexes