Backbone.js Gestion de la mémoire, Rising DOM Node Count

Situation : Je travaille sur une application backbone de page unique très décentement complexe qui pourrait fonctionner pendant 8-12 + heures directement. Pour cette raison, il est nécessaire de veiller à ce que l'application ne fasse pas de fuite et ait une réputation de s'écraser après X heures ou de ralentir de façon spectaculaire.

L'application : L'application est construite sur Backbone (mv *), Zepto (similaire à jquery), Curl (chargeur amd) et Moustache (modèle).

Problème : Je viens de conquérir les auditeurs de l'événement. Le collecteur d'ordures semble faire un bon travail pour nettoyer ces gars, mais le nombre de noeuds DOM n'arrêtera pas d'escalader.

Questions :

  • Existe-t-il un moyen approprié de disposer des nœuds DOM afin qu'ils soient correctement collectés ou ce nœud DOM compte-t-il un total courant qui ne diminuera jamais?
  • Est-ce que quelqu'un connaît l'un de ces cadres pour mal gérer les nœuds DOM? Possible Moustache?
  • Le nombre de nœuds DOM compte-t-il même un chiffre fiable?

Je suis vraiment en train de chercher une avance sur mon aventure pour empêcher ces nœuds DOM de monter. Toute aide ou orientation serait grandement appréciée (et donc actualisée).

J'ai supposé qu'une fois que les auditeurs de l'événement ont été disposés correctement, le nombre de nœuds DOM se gérerait, mais cela ne semble pas être le cas.

Tests


Compte de noeud DOM mal administré

  • Premier test : 6,8 minutes, 110 000 noeuds DOM

Modifier : sans l'enregistrement de la ligne de temps, je redresse le même script pour masquer les liens de manière aléatoire et j'ai pris une capture d'écran autour de la marque de 7 minutes. Après l'arrivée de GC, j'ai eu ces résultats.

Compte de noeud DOM mal administré

  • Deuxième test : 7.1 minutes, 141 000 nœuds DOM (sans l'enregistrement de la chronologie)

Modifier: après correction :

Nœud DOM Count sous contrôle Après Upgrade Backbone et using listenTo et stopListening partout

  • 7 minutes : 6 926 noeuds DOM (voir la réponse marquée ci-dessous).
  • 20 minutes : 6 000 noeuds DOM, 20 auditeurs d'événements, mémoire 20 Mo.
  • 25 minutes : 11 600 nœuds DOM, 44 auditeurs, mémoire 21,7 Mo.
  • 28 minutes : 9 000 noeuds DOM, 22 auditeurs d'événements, mémoire 21,7 Mo.
  • 30 minutes : 13 700 nœuds DOM, 123 auditeurs d'événements, mémoire 21,7.
  • 31 minutes : 7 040 noeuds DOM, 30 auditeurs, mémoire 21,7.

J'ai supposé qu'une fois que les auditeurs de l'événement ont été disposés correctement, le nombre de nœuds DOM se gérerait, mais cela ne semble pas être le cas.

Si je vous ai bien compris, vous essayez de disposer du nœud en enlevant les auditeurs, est-ce le cas?

Notez que l'ajout d'un auditeur d'événement à un noeud DOM n'empêche pas le noeud d'être collecté, la dépendance est en sens inverse: pendant que le nœud est en vie, la fonction d'écoute ne sera pas collectée.

  • Existe-t-il un moyen approprié de disposer des nœuds DOM afin qu'ils soient correctement collectés ou ce nœud DOM compte-t-il un total courant qui ne diminuera jamais?

Pour s'assurer qu'un noeud DOM peut être récupéré, vous devriez

  1. Supprimez le nœud de l'arbre du document.
  2. Effacez toutes les références de javascript au nœud ET à tous les nœuds dans le même sous-arbre que la référence de javascript à l'un des noeuds de la sous-arborescence contiendra un sous-arbre entier.

Il ne suffit donc pas de supprimer les auditeurs d'un noeud pour le rendre collectible. En outre, il n'est pas nécessaire de supprimer les auditeurs d'un noeud si vous souhaitez que le nœud soit collecté.

Le nombre de nœuds DOM devrait diminuer lorsque certains noeuds sont collectés par GC et détruits. Le nombre indique la quantité actuelle de nœuds DOM qui ont été créés, mais pas détruits, de sorte qu'il ne devrait pas se développer indéfiniment à moins qu'il y ait une fuite de mémoire.

  • Le nombre de nœuds DOM compte-t-il même un chiffre fiable?

Oui. Cela devrait être une figure fiable car il est incrémenté chaque fois qu'un nouveau noeud DOM est créé et décrémenté lorsqu'il est détruit. Donc, la mise en œuvre est assez simple pour y faire confiance.

C'est réparé! – UPGRADE BACKBONE. (continuer la lecture)

Nous avons amélioré de Backbone 0.9.2 à Backbone 0.9.10 et mis en place l'écoute et l'arrêt de l'affichage sur chaque vue / modèle / collection. Les résultats sont OMGANTANTES.

Après 7 minutes de fonctionnement du même test de stress, ce sont les résultats: Entrez la description de l'image ici

Résultats : 7,0 minutes, 6 926 nœuds DOM (sans l'enregistrement de la chronologie) et le nombre d'écouteurs d'événements semble BLUE BLADES OF GRASS . Je suis choqué. L'utilisation de la mémoire est également incroyablement faible par rapport aux tests précédents.

Après 18 minutes : le nombre d'écouteurs d'événements est le même, ne dépassant jamais 154 et le nombre de noeuds DOM reste inférieur à 25 000 le temps entier! Il y a évidemment certaines choses qui se glissent (certains composants non backbone qui sont encore utilisés, le plus probablement), mais l'amélioration est étonnante.

Conclusion : Avant cette version de Backbone, nous ne faisions pas très bien de nettoyer les auditeurs dans Backbone lui-même. Les auditeurs des DOM ont été traités correctement, mais pas entre les modèles / les vues / les collections. Beaucoup de rappels concernés ont été liés à Backbone Views, ce qui a empêché le collecteur d'ordures de libérer les noeuds DOM. Beaucoup d'auditeurs / rappels d'événements straggling dans Backbone (pas seulement liés au DOM) créent beaucoup de nœuds DOM straggling qui ne peuvent pas être collectés.

Si ce n'est pas une raison suffisante pour mettre à niveau Backbone, je ne sais pas ce qui est; o

Les nœuds DOM en hausse sont le signe principal d'une fuite de mémoire (habituellement dans le code de notre page). Vous devez donc vous battre contre elle. La technique standard est décrite dans la réponse à cette question.

Le contenu de l'instantané contient trop de détails. Et ce schéma de capture instantané 3 vous aide à filtrer une partie non intéressante de l'instantané et ne montre que les candidats pour une fuite.

Assurez-vous que vous utilisez la dernière version de chrome, comme Chrome Canary. Il devrait s'agir d'une nouvelle instance avec onglet unique sans extensions. Il serait sympa de ne pas avoir de messages d'erreur dans la console, pas de points d'arrêt et ne vous arrêtez pas sur une exception parce que toutes ces choses peuvent affecter la page et, par conséquent, le contenu de l'instantané.

Cette publication pourrait également vous intéresser.

J'ai trouvé une autre façon d'éviter jank

render: function() { this.$el.empty(); var container = document.createDocumentFragment(); // render each subview, appending to our root element _.each(this._views, function(subview) { container.appendChild(subview.render().el) }); this.$el.append(container); } 

Renvoyez-le ici http://ozkatz.github.io/avoiding-common-backbonejs-pitfalls.html