* Ce message a reçu un pouce rouge pour je ne sais quelle raison, aucune explication n'a été donnée, dommage que la raison n'ait pas été donnée (elle était peut-être intéressante ? En tous cela aurait été peut-être plus constructif qu'un pouce rouge), mystère...
J’en connais quelques-un que le hors-sujet agace, je vais avancer l’hypothèse que c’est à cause de ça … Mais ce n’est qu’une hypothèse.
À propos des liens que tu as partagés, Avoiding Memory Leaks est un peu trop vieux (2009). Bien qu’il ne le dise pas clairement, je pense qu’il fait référence au problème des références circulaires sous IE8-.
En revanche, l’autre lien Memory leaks and memory management in JavaScript est intéressant, et j’ai pris le temps de le lire plusieurs fois. Il présente des cas de figure concrets où des fuites de mémoire peuvent se produire, avec à chaque fois un point commun : ce n’est pas un bug du navigateur, c’est le site web ou l’application qui est mal codée.
Le passage sur eval m’a amusé, décidemment cette fonction n’a pas fini de nous montrer qu’elle est evil
Je réalise que c’est vraiment compliqué d’avoir tous ces détails à l’esprit quand on code :
- Le fait que les liens entre nœuds DOM sont toujours à double sens (le sens child et le sens parent ;
- Les trucs pas forcément évidents qui font que des références ne sont pas nettoyées, par exemple setInterval ;
- la mécanique des références au sein d’une closure (en fait, les mécaniques, car ça dépend de l’implémentation) ;
- etc.
D’ailleurs à propos de closures, je suis tombé sur ce billet de 2013 : An interesting kind of JavaScript memory leak.
Pour conclure, c’est une bonne chose d’être prudent et de mettre des grosObjet = null aux endroits stratégiques, juste par précaution.
Je reviens sur ce code de jQuery que j’avais posté dans l’autre conversation :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| empty: function() {
var elem,
i = 0;
for ( ; ( elem = this[ i ] ) != null; i++ ) {
if ( elem.nodeType === 1 ) {
// Prevent memory leaks
jQuery.cleanData( getAll( elem, false ) );
// Remove any remaining nodes
elem.textContent = "";
}
}
return this;
}, |
L’appel à .cleanData() supprime les données que jQuery a attachées à l’élément. Ça inclut celles ajoutées par l’utilisateur via .data(), mais aussi celles ajoutées en interne par jQuery, notamment les gestionnaires d’évènements. Je ne sais pas exactement pourquoi jQuery fait ça.
On peut voir comment ça se passe avec un simple script :
<button>Le bouton</button>
1 2 3
| $("button").on("click", function () {
console.log("Le clic");
} |
Dans la console, déclare une référence sur l’élément DOM nu (non jQuery) par exemple comme ceci :
let bouton = document.querySelector("button")
Puis, commence à taper bouton.j et laisse faire l’autocomplétion. Tu verras qu’il y a une propriété avec un nom aléatoire (dans mon cas j’ai eu bouton.jQuery331059752775723594121) et que cette propriété pointe vers un objet. C’est cet objet qui est nettoyé par .cleanData().
La doc de .data() indique que c’est pour prévenir les références circulaires :
The jQuery.data() method allows us to attach data of any type to DOM elements in a way that is safe from circular references and therefore from memory leaks.
—
https://api.jquery.com/jQuery.data/
Mais d’après le MDN, les ramasse-miettes de tous les navigateurs depuis 2012 utilisent la stratégie mark and sweep avec laquelle les références circulaires ne sont plus un problème.
Alors, est-ce que jQuery fait ainsi juste pour les anciens navigateurs ? Normalement non, car il est clairement indiqué que la version majeure 3 n’est compatible qu’à partir d’IE9+.
Ça peut être un oubli, ou alors un bout de code qu’ils ont préféré ne pas retirer. Ou encore c’est juste par précaution.
Pour l’instant, je n’ai pas d’explication à ce mystère et je vais continuer à chercher.
Pour répondre à cette question :
Est-il possible de connaitre la consommation en mémoire d'une page web ? Comment la libérer ?
Danielhagnoul a déjà fourni quelques liens bien utiles, mais je rajoute que les consoles des différents navigateurs offrent aujourd’hui des outils satisfaisants pour examiner la mémoire d’une page web. Même s’il faut préciser que celle de Firefox n’est pas encore aussi facile d’utilisation que celle de Chrome.
Un guide d’utilisation des outils mémoire de Chrome : Fix memory problems.
J’ai moi-même mené quelques tests sous Firefox pour tenter de mettre jQuery en échec, et j’ai cru avoir réussi dans un premier temps, je voyais la mémoire de la page augmenter petit à petit. C’était un piège : le ramasse-miette dormait. Et puis il s’est réveillé d’un coup et il a tout supprimé.
Ça m’a surpris car je pensais que le ramasse-miettes de Firefox était incrémental, mais visiblement il y a quelque chose que j’ai compris de travers
Partager