javascript aktivieren firefox - Suchen von JavaScript-Speicherverlusten mit Chrome




4 Answers

Ein guter Workflow, um Speicherlecks zu finden, ist die Drei-Snapshot- Technik, die zuerst von Loreena Lee und dem Gmail-Team verwendet wurde, um einige ihrer Speicherprobleme zu lösen. Die Schritte sind im Allgemeinen:

  • Mache einen Heap-Snapshot.
  • Sachen machen.
  • Nehmen Sie einen anderen Heap-Snapshot.
  • Wiederhole das gleiche Zeug.
  • Nehmen Sie einen anderen Heap-Snapshot.
  • Filtern Sie Objekte, die in Snapshot 3 in der Ansicht "Zusammenfassung" zwischen den Snapshots 1 und 2 zugewiesen wurden.

Für Ihr Beispiel habe ich den Code so angepasst, dass dieser Prozess angezeigt wird (Sie können ihn here ), indem Sie die Erstellung der Backbone-Ansicht bis zum Klickereignis der Schaltfläche "Start" verzögern. Jetzt:

  • Führen Sie den HTML-Code aus (lokal gespeichert unter Verwendung dieser address ) und erstellen Sie einen Snapshot.
  • Klicken Sie auf Start, um die Ansicht zu erstellen.
  • Mach einen anderen Schnappschuss.
  • Klicken Sie auf Entfernen.
  • Mach einen anderen Schnappschuss.
  • Filtern Sie Objekte, die in Snapshot 3 in der Ansicht "Zusammenfassung" zwischen den Snapshots 1 und 2 zugewiesen wurden.

Jetzt sind Sie bereit, Speicherlecks zu finden!

Sie werden Knoten von einigen verschiedenen Farben bemerken. Rote Knoten haben keine direkten Referenzen von Javascript auf sie, sind jedoch am Leben, da sie Teil einer getrennten DOM-Struktur sind. Es kann einen Knoten in der Baumstruktur geben, auf den von Javascript referenziert wird (möglicherweise als eine Schließung oder eine Variable), aber es verhindert zufällig, dass die gesamte DOM-Baumstruktur als Garbage Collection behandelt wird.

Gelbe Knoten haben jedoch direkte Referenzen von Javascript. Suchen Sie nach gelben Knoten in demselben DOM-Baum, um Referenzen aus Ihrem Javascript zu finden. Es sollte eine Kette von Eigenschaften geben, die vom DOM-Fenster zum Element führen.

In Ihrem Fall können Sie ein HTML-Div-Element sehen, das als rot markiert ist. Wenn Sie das Element erweitern, sehen Sie, dass auf eine "Cache" -Funktion verwiesen wird.

Wählen Sie die Zeile und in Ihrer Konsole geben Sie $ 0 ein, dann sehen Sie die aktuelle Funktion und den Ort:

>$0
function cache( key, value ) {
        // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
        if ( keys.push( key += " " ) > Expr.cacheLength ) {
            // Only keep the most recent entries
            delete cache[ keys.shift() ];
        }
        return (cache[ key ] = value);
    }                                                     jquery-2.0.2.js:1166

Hier wird auf Ihr Element verwiesen. Leider gibt es nicht viel, was Sie tun können, es ist ein interner Mechanismus von jQuery. Aber, nur für Testzwecke, gehen Sie die Funktion und ändern Sie die Methode zu:

function cache( key, value ) {
    return value;
}

Jetzt, wenn Sie den Vorgang wiederholen, sehen Sie keinen roten Knoten :)

Dokumentation:

enable android

Ich habe einen sehr einfachen Testfall erstellt, der eine Backbone-Ansicht erstellt, einen Handler an ein Ereignis anfügt und eine benutzerdefinierte Klasse instanziiert. Ich glaube, dass durch Klicken auf die Schaltfläche "Entfernen" in diesem Beispiel alles bereinigt wird und es keine Speicherlecks mehr geben sollte.

Eine Anleitung für den Code finden Sie hier: http://jsfiddle.net/4QhR2/

// scope everything to a function
function main() {

    function MyWrapper() {
        this.element = null;
    }
    MyWrapper.prototype.set = function(elem) {
        this.element = elem;
    }
    MyWrapper.prototype.get = function() {
        return this.element;
    }

    var MyView = Backbone.View.extend({
        tagName : "div",
        id : "view",
        events : {
            "click #button" : "onButton",
        },    
        initialize : function(options) {        
            // done for demo purposes only, should be using templates
            this.html_text = "<input type='text' id='textbox' /><button id='button'>Remove</button>";        
            this.listenTo(this,"all",function(){console.log("Event: "+arguments[0]);});
        },
        render : function() {        
            this.$el.html(this.html_text);

            this.wrapper = new MyWrapper();
            this.wrapper.set(this.$("#textbox"));
            this.wrapper.get().val("placeholder");

            return this;
        },
        onButton : function() {
            // assume this gets .remove() called on subviews (if they existed)
            this.trigger("cleanup");
            this.remove();
        }
    });

    var view = new MyView();
    $("#content").append(view.render().el);
}

main();

Mir ist jedoch unklar, wie man den Profiler von Google Chrome verwenden kann, um zu überprüfen, ob dies tatsächlich der Fall ist. Es gibt eine Unmenge von Dingen, die auf dem Heap-Profiler-Snapshot auftauchen, und ich habe keine Ahnung, wie man das, was gut / schlecht ist, dekodiert. Die Tutorials, die ich bisher gesehen habe, sagen mir entweder, dass ich den Snapshot-Profiler verwenden soll, oder geben mir ein sehr detailliertes Manifest darüber, wie der gesamte Profiler funktioniert. Ist es möglich, den Profiler einfach als Werkzeug zu benutzen, oder muss ich wirklich verstehen, wie das Ganze konstruiert wurde?

EDIT: Tutorials wie diese:

Gmail-Speicherleckfixierung

Verwenden von DevTools

Sind Vertreter von etwas von dem stärkeren Material da draußen, von dem, was ich gesehen habe. Abgesehen von der Einführung des Konzepts der 3-Snapshot-Technik , finde ich, dass sie sehr wenig praktisches Wissen bieten (für einen Anfänger wie mich). Das 'Using DevTools'-Tutorial funktioniert nicht anhand eines realen Beispiels, daher ist seine vage und allgemeine begriffliche Beschreibung der Dinge nicht allzu hilfreich. Was das "Google Mail" -Beispiel betrifft:

Also hast du ein Leck gefunden. Was jetzt?

  • Untersuchen Sie den Haltepfad von ausgelaufenen Objekten in der unteren Hälfte des Profile-Bedienfelds

  • Wenn die Zuweisungsseite nicht einfach abgeleitet werden kann (z. B. Ereignis-Listener):

  • Instrumentieren Sie den Konstruktor des Halteobjekts über die JS-Konsole, um den Stack-Trace für Zuordnungen zu speichern

  • Verschluss verwenden? Aktivieren Sie das entsprechende vorhandene Flag (z. B. goog.events.Listener.ENABLE_MONITORING), um die creationStack-Eigenschaft während der Konstruktion festzulegen

Ich bin verwirrt, nachdem ich das gelesen habe, nicht weniger. Und wiederum sagt es mir nur, dass ich Dinge tun soll , nicht wie ich sie machen soll. Aus meiner Sicht ist die gesamte Information entweder zu vage oder würde nur für jemanden Sinn machen, der den Prozess bereits verstanden hat.

Einige dieser spezifischeren Probleme wurden in Jonathan Naguins Antwort unten angesprochen .




Grundsätzlich müssen Sie sich die Anzahl der Objekte in Ihrem Heap-Snapshot ansehen. Wenn die Anzahl der Objekte zwischen zwei Snapshots zunimmt und Sie Objekte gelöscht haben, liegt ein Speicherleck vor. Mein Rat ist, in Ihrem Code nach Event-Handlern zu suchen, die nicht losgelöst werden.




Es gibt ein Einführungsvideo von Google, das sehr hilfreich sein wird, um JavaScript-Speicherlecks zu finden.

youtube.com/watch?v=L3ugr9BJqIs




Ich habe den Ratschlag, einen Heap-Snapshot zu machen, sie sind hervorragend für die Erkennung von Speicherlecks geeignet, Chrome ist eine ausgezeichnete Aufgabe der Snapshot-Erstellung.

In meinem Forschungsprojekt für meinen Abschluss habe ich eine interaktive Webanwendung erstellt, die viele Daten in 'Schichten' erzeugen musste, viele dieser Schichten würden in der Benutzeroberfläche 'gelöscht' werden, aber aus irgendeinem Grund war die Erinnerung nicht Mit dem Snapshot-Tool konnte ich feststellen, dass JQuery eine Referenz auf das Objekt behalten hatte (die Quelle war, als ich versuchte, ein .load() Ereignis auszulösen, das die Referenz trotz des außerhalb des Gültigkeitsbereichs liegenden Bereichs behielt). Wenn Sie diese Informationen zur Hand haben und mein Projekt im Alleingang gespeichert haben, ist das ein sehr nützliches Werkzeug, wenn Sie die Bibliotheken anderer Leute verwenden, und Sie haben das Problem, dass Referenzen den GC von seiner Arbeit abhalten.

BEARBEITEN: Es ist auch nützlich, vorausschauend zu planen, welche Aktionen Sie durchführen werden, um den Zeitaufwand für Snapshots zu minimieren, Hypothesen aufzustellen, was das Problem verursachen könnte, und jedes Szenario zu testen und Snapshots vorher und nachher zu erstellen.




Related