Angular.js Speicherlecks, wann sollte ich mir Sorgen machen?

8

Also habe ich diese recht große Anwendung auf eckigen, viel verschachtelten Zuständen, vielen Direktiven, Datentabellen und so weiter aufgebaut.

Wir haben kürzlich entschieden, auf eine einzelne Seite umzusteigen, anstatt nur ein paar kleine einzelne Apps zu haben (zB Artikel, Leute, Dashboard waren jeweils eine kleine Single-Page-App), also habe ich mich etwas mehr mit Performance beschäftigt. In Chrom merkt man etwas nicht, auf firefox auf der anderen Seite denke ich, dass es mit der Zeit langsamer wird.

Also habe ich mit drei Snapshot-Techniken angefangen, um zu sehen, was los ist. Aber ich bin mir nicht ganz sicher, was ich davon halten soll.

BILD

  • Snapshot-Größe verdoppelt seine Größe jeden Snapshot genommen (1. 15mb, 2. 67MB, 3. 120MB), bedeutet das etwas?
  • es gibt viele rote dom, 4000 von roten divs zum Beispiel

Jetzt habe ich das Gefühl, dass diese roten divs, Spannen und Anker hauptsächlich meine Schuld sind, ich mache etwas nicht so übliches Zeug, um diese Datentabellen zu rendern, benutze diese Anweisung, die ich gemacht habe, und ich fühle auch, dass einige von Heap Objekte sind das Ergebnis, wenn diese dom-Elemente nicht korrekt entfernt werden.

Das macht die Tabellenrichtlinie im Wesentlichen

%Vor%

Der Grund, warum ich das überhaupt mache, ist, dass, wenn ich verschachtelte ng-repeat für Zeilen und Spalten und <table-cell> Direktive für Zellen verwendet habe, es viel zu lange gerendert hat, sogar mit nur etwa 6 Spalten und 50 Zeilen.

Ich glaube also, dass keine dieser divs innerhalb dieser Tabelle korrekt entfernt wird, so dass sie jedes Mal, wenn diese Tabellenanweisung geladen wird, aufstocken.

Nun, selbst wenn ich mich mit diesem abgetrennten DOM-Baum beschäftige ... was ist mit all den anderen Sachen, woher weiß ich, was ich versuchen sollte und mit denen ich mich beschäftige und die für eckige üblich sind und die Leistung nicht wirklich beeinträchtigen?

// Tabellenreferenz auf Plunker bearbeiten Ссылка

    
foxx 25.04.2014, 09:34
quelle

2 Antworten

6

Das Leck wurde tatsächlich durch eine andere, völlig harmlos aussehende Anweisung verursacht, die im Header der Tabelle verwendet wurde und nichts anderes tat, als ein Array von "sort items" zu erstellen und dann mit ng-repeat .. und was noch schlimmer es wurde nicht durch irgendetwas verursacht, was ich innerhalb dieser Direktive tat, sondern durch seine replace: true .. Gott weiß warum, ich werde versuchen, es auf Plunker zu reproduzieren und über Github zu berichten.

Da es fast unmöglich war, zu finden, welcher Teil der App es verursachte, nur indem ich auf den Heap-Bericht schaute, fuhr ich fort und löschte alle anderen Teile der App, aber die, die ich vermutete, verursachte es, dann fand ich heraus es war nicht dieser, also fuhr ich fort und las alle anderen weiter.

Nachdem ich die eigentliche problematische Direktive herausgefunden hatte, tat ich das Gleiche, löschte Teile seines Codes, bis wirklich nichts darin war.

Dann war es offensichtlich, dass es eine der Optionen der Direktive war, dann fand ich heraus, dass Ersetzen es verursachte.

    
foxx 26.04.2014, 15:43
quelle
5

Diese Richtlinie gibt nichts aus. Ich habe deinen PLNKR gespreizt, viel mehr Objekte hinzugefügt, um es bemerkbar zu machen, wenn das undicht war, und einen Knopf hinzugefügt, der den Tisch neu lädt. Es wartet eine Sekunde und füllt es dann wieder auf.

Knoten werden eliminiert und neu erstellt. Die Schritte zum Suchen der Lecks sind:

  • Aufnahme starten
  • Warte 2 Sekunden
  • Drücken Sie die Taste
  • Warte 10 Sekunden
  • Stoppen Sie die Aufnahme

Wenn Sie das genau dreimal machen (so haben Sie den gleichen Speicherzustand), sehen Sie, dass der gleiche Speicher verwendet wird:

Sie können das gespaltene plnkr

überprüfen

Danach kann ich nur versuchen zu erraten, was das Problem sein könnte. Ich werde Ihnen ein paar Vorschläge geben, basierend auf dem, was ich entdeckt habe: https://stackoverflow.com/questions/20654684/how-to-catch-memory-leaks-in-an-angular-application "> hier .

  • Überprüfen Sie Richtlinien, sie sind normalerweise die Ursache. Die frickingTable scheint nichts schädlich zu machen, aber andere Bräuche könnten, auch wenn sie nicht deins sind, einfach passieren.
  • Wenn die Tabelle mit einer Art "polling" gefüllt wird, leeren Sie das Objekt vor der Neuzuweisung. Also, wenn Sie den gespaltenen PLNKR sehen, werden Sie sehen, dass ich zuerst items auf null setze und dann zuweisen. Das sollte der Weg sein. In der PLNKR habe ich es gemacht, damit es auffällt (dass die Tabelle neu gefüllt wird), aber ich habe festgestellt, dass Browser dazu neigen, Referenzen irgendwie beizubehalten, wenn Sie keine Objekte / Arrays säubern. Ich bereinige Arrays mit .length = 0 und Objekten mit null , wodurch alle möglichen Verweise auf dieses Objekt für die GCed bereit sind und keine Lecks verursachen. Das klingt albern, aber ich habe es in Angular und auch in Backbone gesehen, also muss es eine Browser-Sache sein.

Ich kann nicht wirklich an etwas anderes denken, ohne mehr Code zu sehen. Hoffe, das zeigt Ihnen in die richtige Richtung, Lecks sind nervig, um es gelinde auszudrücken.

    
Antonio Laguna 25.04.2014 22:01
quelle