6
votes

Fuite de mémoire impliquant des demandes de jQuery Ajax

J'ai une page Web qui fuit la mémoire dans l'IE8 et la Firefox; L'utilisation de la mémoire affichée dans l'explorateur de processus Windows continue de croître au fil du temps.

La page suivante demande l'URL "non planifié.json", qui est un fichier statique qui ne change jamais (bien que je fixe mon Cache-Control Code> HTTP en-tête sur NON-CACHE CODE> Pour vous assurer que la demande AJAX passe toujours). Lorsqu'il obtient les résultats, il dégage une table HTML, des boucles sur le tableau JSON, il est revenu du serveur et ajoute de manière dynamique une ligne à une table HTML pour chaque entrée de la matrice. Ensuite, il attend 2 secondes et répète ce processus. P>

Voici toute la page Web: P>

function resetTable() {
    $("#content tbody").empty();
    for(var i=0; i<1000; i++) {
        $("#content tbody").append("<tr><td>" + "DBOSS-095" + "</td>"
            + "<td>" + 4 + "</td>"
            + "<td>" + "09/18/2009 11:51:06" + "</td>"
            + "<td>" + 1 + "</td>"
            + "<td>" + 1 + "</td></tr>");
    }
    setTimeout(resetTable, 2000);
}
$(resetTable);


3 commentaires

Question muette, mais comme il est ajouté au corps de chaque extraction, comment peut-il utiliser la même quantité de mémoire?


Il rétablit le Todbon avant de l'ajouter. Je m'attendrais à ce que les rangées vidées obtiennent des ordures recueillies, bien que quelqu'un me dise certainement si je me trompe à ce sujet.


Dans IE6 / 7/8, vous ne pouvez pas vraiment retirer un élément DOM créé de manière dynamique sans effectuer une étrange de travail sur NULL l'innerhtml (set innerhtml = "")


3 Réponses :


4
votes

Je ne suis pas sûr de la fuite, mais votre fonction réinitialisable () est très inefficace. Essayez d'abord de résoudre ces problèmes et voyez où vous vous retrouvez.

  • Ne pas ajouter à la DOM dans une boucle. Si vous devez do DOM manipulation, puis appendez-le à un fragment de document, puis déplacez ce fragment vers le DOM.
  • Mais innerhtml est plus rapide que la manipulation DOM de toute façon, utilisez-la si vous le pouvez.
  • Stocker jQuery se jette en variables locales - pas besoin de réexécuter le sélecteur à chaque fois.
  • stockez également des références répétées dans une variable locale.
  • Lors de l'itération sur une collection de toutes sortes, stockez également la longueur dans une variable locale.

    nouveau code: xxx

    références:


2 commentaires

Ce sont de grandes suggestions, mais malheureusement, je vois toujours la fuite de mémoire lors de l'exécution de votre code. Tout est exactement pareil sauf que j'ai remplacé "Test.php" avec "Unplanned.jp" - Je suppose que vous avez fait une page test.php pour tester cela vous-même, ce qui est vraiment génial et utile. Donc, merci pour l'entrée et j'utiliserai certainement certaines de ces techniques à l'avenir, mais si vous avez d'autres idées sur ce qui pourrait causer cette utilisation de la mémoire, j'aimerais bien les entendre.


J'ai fait. Je vais réfléchir à ce problème d'autres et voyez si je peux venir avec n'importe quoi. Quelle est la taille des données que vous retournez à l'AJAX?



0
votes

S'il vous plaît corrigez-moi si je me trompe ici mais ne peut-il pas dire (FN) empêche la libération de l'espace mémoire de l'appelant? De sorte que toutes les variables / la mémoire allouées lors de la méthode réinitialisable (lignes) restent allouées jusqu'à la fin de la boucle?

Si c'est le cas, poussez la construction de chaîne et l'annexe de la logique à une méthode différente peut être un peu meilleure que ces objets obtiendraient libéré de chaque appel et seulement la mémoire de la valeur retournée (dans ce cas, soit le balisage de la chaîne, soit rien si la nouvelle méthode que la nouvelle méthode a annoncé ()) resterait en mémoire.

Essence:

Appel initial à Kickoff

-> Appels Resettable ()

-> -> Settimeout appels à nouveau

-> -> -> Appels réinstallables () à nouveau

-> -> -> -> Continuer jusqu'à infini

Si le code ne résout jamais vraiment, l'arbre continuerait de croître.

Une autre façon de libérer une certaine mémoire basée sur ce type serait comme le code ci-dessous: xxx

Ceci appendra le balisage à votre Tody, puis terminer cette partie de la pile . Je suis à peu près sûr que chaque itération de "lignes" restera toujours en mémoire; Cependant, la chaîne de balisage et tels devraient libérer finalement.

Encore une fois ... Cela fait longtemps que je n'ai pas regardé Settimeout à ce niveau bas afin que je puisse être complètement faux ici. En anyclette, cela ne va pas enlever la fuite et ne diminuera que le taux de croissance. Cela dépend de la manière dont le collecteur des ordures des moteurs JavaScript dans l'utilisation traite des boucles de Settimeout comme vous l'avez ici.


1 commentaires

Merci pour la suggestion - j'ai eu ma page de travail grâce à la suggestion de Toran ci-dessus, mais à l'avenir, je vais vérifier vos idées et voir si elles fonctionnent également. S'ils le font, j'accepterai probablement votre suggestion à la place, car c'est beaucoup plus simple que le plugin JQuery que Toran a écrit, bien que je devine que son approche est probablement le seul moyen réel d'obtenir ma page pour ne pas fuir la mémoire.



11
votes

Je ne sais pas pourquoi Firefox n'est pas heureux avec ceci, mais je peux dire de l'expérience que dans IE6 / 7/8, vous devez définir innerhtml = ""; Sur l'objet, vous voulez supprimer du DOM. (Si vous avez créé cet élément DOM de manière dynamique, c'est)

$ ("# contenu Tody"). vide (); code> pourrait ne pas relâcher ces éléments DOM générés dynamiquement. P>

Essayez plutôt quelque chose comme le ci-dessous (c'est un plugin JQuery que j'ai écrit pour résoudre le problème). P>

jQuery.fn.removefromdom = function(s) {
    if (!this) return;

    var bin = $("#IELeakGarbageBin");

    if (!bin.get(0)) {
        bin = $("<div id='IELeakGarbageBin'></div>");
        $("body").append(bin);
    }

    $(this).children().each(
            function() {
                bin.append(this);
                document.getElementById("IELeakGarbageBin").innerHTML = "";
            }
    );

    this.remove();

    bin.append(this);
    document.getElementById("IELeakGarbageBin").innerHTML = "";
};


1 commentaires

Merci beaucoup, cela corrige mon problème. J'ai modifié ma question pour signaler certaines limitations de ce plugin et posté mon code maintenant à la fuite de mémoire et non-mémoire pour montrer aux personnes comment appliquer votre plugin sur ma page.