2012-12-06 9 views
7

Ich entwickle derzeit eine Website, die reines javascript ist und stark auf die jQuery & jQuery UI-Bibliotheken (diese Website ist nicht für die allgemeine Öffentlichkeit bestimmt, daher progressive Verbesserung ist keine strenge Voraussetzung für dieses Projekt). Ich bin ein erhebliches Speicherleck stoße auf der Ausführung den folgenden Code:Identifizieren Sie JavaScript-Schließungen mit Entwickler-Tools

oDialogBox = $("<div>...</div>"); 
/* Add useful things to the dialog box here */ 
oDialogBox.appendTo("body"); 
oDialogBox.dialog({ 
    /* Other dialog box settings here */ 
    close: function(event, ui) { 
     oDialogBox.dialog("destroy"); 
     oDialogBox.remove(); 
     oDialogBox = null; 
    } 
}); 

Zu jedem beliebigen Zeitpunkt in diesem Dialogfeld, ich schaff', zu entfernen und eine große Anzahl von Instanzen von jQuery UI-Tasten ändern, multiselects (pro dem Multiselect-Widget erstellt von Eric Hynds) und auf Click-Event-Handler. Laut der jQuery UI-Dokumentation sollte der Aufruf von .remove() auf der oDialogBox zur Folge haben, dass alle untergeordneten Widgets nicht gebunden und gelöscht werden. Mein freistehender DOM-Baum zeigt jedoch eine signifikante Anzahl von Müllelementen, die der GC nicht sammelt.

Es ist sehr wahrscheinlich, dass ich eine große Anzahl von Verschlüssen verpasst habe, die sicher abgeschlossen werden müssen. Wie gehe ich folgendermaßen vor:

1) Wie identifiziere ich, welche Closures ein bestimmtes loses DOM-Objekt am Leben erhalten (entweder in Firefox oder Chrome)?

2) Unter der Annahme, dass der vollständige Satz von Closures identifiziert wird, muss über die Nullung der Variablen hinaus noch alles getan werden, um das DOM-Element für die Garbage Collection zu markieren?

3) Ich habe auch bemerkt, dass meine Liste der von der Seite gespeicherten Arrays riesig ist und Verweise auf DOM-Elemente enthält, die vom GC nicht erfasst werden. Gibt es eine dokumentierte Best Practice, um Arrays aus Javascript zu entfernen und alle Elemente zum Löschen vormerken zu können? (Hinweis: Dies ist ein aktueller Hauptverdächtiger für die Quelle des Speicherlecks.)

+0

"* Liste der Arrays, die Verweise auf DOM-Elemente enthalten *" - könnte das der Grund sein, dass die DOM-Elemente nicht als Garbage Collection erfasst werden? Wie überprüfen Sie diese Liste? – Bergi

+0

Bei Verwendung der Chrome-Entwicklungstools habe ich mit dem Profiler-Tool Heap-Snapshots erstellt. Nach dem Ausführen meines Tests wurden fast 50 MB zusätzlicher Speicher im Heap belegt. Dies wurde vom Profiler als in "(Array)" -Objekten gespeichert identifiziert. Die Stichprobenprüfung hat jQuery-Eigenschaften für Elemente in der DOM-Baumstruktur gefunden. Ich habe auch Hinweise auf leere Arrays gefunden, die nicht gesammelt werden.Ich versuche immer noch zu identifizieren, ob eines der Arrays, die ich in meinem Code definiere, in der Liste der 10k + -Objekte versteckt ist. –

Antwort

1

Ich habe Angst, dass ich keine großartige Antwort für # 1 habe. Ich habe dafür selbst keine wirklich guten Werkzeuge gefunden, auch wenn die Entwicklungswerkzeuge in den letzten Jahren so gut geworden sind. Der beste Rat, den ich geben kann, ist, die Dinge immer so klein wie möglich zu halten. Wenn die Dinge nicht entkommen, ist es im Allgemeinen leichter, einfach herauszufinden, wo die Referenzen sein müssen.

Zu # 2 kann es weitere Bedenken geben. Wenn das durch die Variable v1 referenzierte Objekt über die freien Variablen einer Funktion schließt, reicht das Entfernen von v1 nicht aus, um sie für die Garbage Collection geeignet zu machen, wenn eine andere Variable in einer anderen Funktion über v1 schließt. Ich denke also, wenn Sie wirklich den "kompletten Satz von Schließungen" meinen, dann sollten Sie alles haben. Aber das könnte haarig werden. Wenn die meisten Objekte Referenzen nur in engen Bereichen haben, sind diese Probleme viel weniger streng.

Für # 3, welche Arten von Arrays diskutieren Sie? Wenn es sich um jQuery-Sammlungen handelt, haben Sie vielleicht einfach zu viele davon. Der einzige Grund, warum ich weiß, dass sie für eine lange Zeit dort bleiben, ist, Event-Handler an sie zu binden, und das wird fast immer besser durch Ereignisdelegierung auf Elternelementen gehandhabt. Wenn es sich um eigene benutzerdefinierte Arrays handelt, haben Sie wirklich einen guten Grund, Referenzen darauf in Arrays zu speichern, die für längere Zeit bestehen bleiben? Ich habe selten einen gefunden.

+0

Als ich Ihre Antwort zuerst las, war meine unmittelbare Reaktion "Nein, das Array ist vollständig notwendig." Aber nachdem ich über Nacht darüber nachgedacht habe, benutze ich wirklich nur das Array, um eine dynamische Liste spezieller divs für die Formulardatensammlung beizubehalten, wenn der Benutzer auf "submit" klickt. Derselbe Trick könnte wahrscheinlich mit einer umfangreicheren Verwendung von Klassen für die Objekte und den jQuery-Selektor durchgeführt werden. –

+0

Eine andere Möglichkeit ist ein Array ihrer IDs, wenn die Elemente ids haben. Dies ist viel leichter und möglicherweise zielgerichteter als DOM-Klassen. –

Verwandte Themen