Speicherprobleme beheben

Kayce Basken
Kayce Basken

Hier erfahren Sie, wie Sie mit Chrome und den Entwicklertools Speicherprobleme identifizieren, die sich auf die Seitenleistung auswirken, wie z. B. Speicherlecks, Auslastung des Arbeitsspeichers und häufige Speicherbereinigungen.

Zusammenfassung

  • Mit dem Task-Manager von Chrome können Sie überprüfen, wie viel Speicher Ihre Seite derzeit belegt.
  • Mit Zeitachsenaufzeichnungen die Arbeitsspeichernutzung im Zeitverlauf visualisieren.
  • Identifizieren Sie mit Heap-Snapshots getrennte DOM-Baumstrukturen (eine häufige Ursache für Speicherlecks).
  • Mithilfe von Zeitachsenaufzeichnungen für die Zuweisung finden Sie heraus, wann neuer Speicher in Ihrem JS-Heap zugewiesen wird.

Überblick

Im Sinne des RAIL-Modells sollten bei Ihren Maßnahmen die Nutzer im Mittelpunkt stehen.

Arbeitsspeicherprobleme sind wichtig, da sie oft von Nutzenden wahrgenommen werden. Nutzer können Speicherprobleme so wahrnehmen:

  • Die Leistung einer Seite nimmt mit der Zeit ab. Dies ist möglicherweise ein Symptom für ein Speicherleck. Ein Speicherleck liegt vor, wenn ein Fehler auf der Seite dazu führt, dass die Seite im Laufe der Zeit immer mehr Arbeitsspeicher verwendet.
  • Die Leistung einer Seite ist durchgehend schlecht. Dies ist möglicherweise ein Symptom für eine überladene Erinnerung. Wenn eine Seite mehr Arbeitsspeicher belegt, als für eine optimale Seitengeschwindigkeit erforderlich ist, spricht man von Arbeitsspeicher-Bloat.
  • Die Leistung einer Seite verzögert sich oder scheint häufig zu pausieren. Dies ist möglicherweise ein Symptom häufig auftretender automatischer Speicherbereinigungen. Bei der automatischen Speicherbereinigung gibt der Browser Arbeitsspeicher frei. Der Browser entscheidet, wann dies geschieht. Während der Erfassung wird die Ausführung aller Skripts angehalten. Wenn also der Browser aufgrund der automatischen Speicherbereinigung häufig arbeitet, wird die Skriptausführung häufig pausiert.

Überladene Erinnerung: Wie viel ist „zu viel“?

Ein Speicherleck ist einfach zu definieren. Wenn eine Website nach und nach immer mehr Arbeitsspeicher belegt, ist ein Datenleck aufgetreten. Aber es ist etwas schwieriger, zu viel Arbeitsspeicher zu finden. Was bedeutet „zu viel Arbeitsspeicher verbrauchen“?

Hier gibt es keine festen Zahlen, da verschiedene Geräte und Browser unterschiedliche Funktionen haben. Dieselbe Seite, die auf einem High-End-Smartphone reibungslos ausgeführt wird, kann auf einem Low-End-Smartphone abstürzen.

Das Entscheidende ist hier die Verwendung des RAIL-Modells und die Konzentration auf Ihre Nutzer. Finden Sie heraus, welche Geräte bei Ihren Nutzern beliebt sind, und testen Sie Ihre Seite dann auf diesen Geräten. Wenn das Problem dadurch nicht behoben wird, kann es sein, dass die Seite die Speicherkapazität des jeweiligen Geräts überschreitet.

Arbeitsspeichernutzung in Echtzeit mit dem Task-Manager von Chrome überwachen

Verwenden Sie den Task-Manager von Chrome als Ausgangspunkt für die Untersuchung Ihrer Arbeitsspeicherprobleme. Der Task-Manager ist eine Echtzeitüberwachung, die Ihnen anzeigt, wie viel Speicher eine Seite derzeit verwendet.

  1. Drücken Sie die Umschalttaste + Esc oder rufen Sie das Chrome-Hauptmenü auf und wählen Sie Weitere Tools > Task-Manager aus, um den Task-Manager zu öffnen.

    Task-Manager öffnen

  2. Klicken Sie im Task-Manager mit der rechten Maustaste auf die Kopfzeile der Tabelle und aktivieren Sie JavaScript-Arbeitsspeicher.

    JS-Arbeitsspeicher aktivieren

Diese beiden Spalten geben unterschiedliche Informationen zur Speichernutzung Ihrer Seite an:

  • Die Spalte Arbeitsspeicher steht für den nativen Arbeitsspeicher. DOM-Knoten werden im nativen Arbeitsspeicher gespeichert. Wenn dieser Wert ansteigt, werden DOM-Knoten erstellt.
  • Die Spalte JavaScript-Speicher entspricht dem JS-Heap. Diese Spalte enthält zwei Werte. Der Wert, an dem Sie interessiert sind, ist die aktuelle Zahl (die Zahl in Klammern). Die Zahl für die Live-Anzeige gibt an, wie viel Speicher die erreichbaren Objekte auf Ihrer Seite belegen. Wenn diese Zahl steigt, werden entweder neue Objekte erstellt oder die Anzahl der vorhandenen Objekte nimmt zu.

Speicherlecks mit Leistungsaufzeichnungen visualisieren

Der Bereich „Leistung“ kann Ihnen auch als Ausgangspunkt für Ihre Untersuchung dienen. Im Bereich „Leistung“ können Sie die Speichernutzung einer Seite im Zeitverlauf visualisieren.

  1. Öffnen Sie in den Entwicklertools den Bereich Leistung.
  2. Aktivieren Sie das Kästchen Arbeitsspeicher.
  3. Nehmen Sie eine Aufzeichnung auf.

Sehen Sie sich den folgenden Code an, um Aufzeichnungen des Performance-Speichers zu veranschaulichen:

var x = [];

function grow() {
  for (var i = 0; i < 10000; i++) {
    document.body.appendChild(document.createElement('div'));
  }
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Jedes Mal, wenn die im Code referenzierte Schaltfläche gedrückt wird, werden zehntausend div-Knoten an den Dokumenttext angehängt und ein String von einer Million x-Zeichen wird in das x-Array verschoben. Wenn Sie diesen Code ausführen, wird eine Zeitachse wie im folgenden Screenshot erstellt:

Beispiel für einfaches Wachstum

Zuerst eine Erläuterung der Benutzeroberfläche. Das HEAP-Diagramm im Bereich Übersicht (unter NET) stellt den JS-Heap dar. Unterhalb des Bereichs Übersicht befindet sich der Bereich Zähler. Hier sehen Sie die Arbeitsspeichernutzung aufgeschlüsselt nach JS-Heap (wie beim HEAP-Diagramm im Bereich Übersicht), Dokumenten, DOM-Knoten, Listenern und GPU-Arbeitsspeicher. Wenn Sie ein Kästchen deaktivieren, wird es in der Grafik ausgeblendet.

Nun sehen wir uns eine Analyse des Codes im Vergleich zum Screenshot an. Wenn Sie sich den Knotenzähler (das grüne Diagramm) ansehen, können Sie sehen, dass er korrekt mit dem Code übereinstimmt. Die Anzahl der Knoten erhöht sich in einzelnen Schritten. Sie können davon ausgehen, dass jede Erhöhung der Knotenzahl ein Aufruf von grow() ist. Die JS-Heap-Grafik (die blaue Grafik) ist nicht so geradlinig. In Übereinstimmung mit den Best Practices ist der erste Rückgang in Wirklichkeit eine erzwungene automatische Speicherbereinigung, die durch Drücken der Schaltfläche Automatische Speicherbereinigung erreicht wird. Im Verlauf der Aufzeichnung sehen Sie, dass die JS-Heap-Größe ansteigt. Das ist normal und erwartet: Der JavaScript-Code erzeugt bei jedem Klick auf eine Schaltfläche die DOM-Knoten und erledigt viel Arbeit, wenn er die Zeichenfolge aus einer Million Zeichen erzeugt. Das Entscheidende ist hier die Tatsache, dass der JS-Heap höher endet als er begonnen hat (der „Anfang“ hier ist der Punkt nach der erzwungenen automatischen Speicherbereinigung). Wenn Sie in der realen Welt dieses Muster der zunehmenden JS-Heap-Größe oder Knotengröße sehen würden, würde dies möglicherweise auf ein Speicherleck hindeuten.

Speicherlecks in getrennten DOM-Baumstrukturen mit Heap-Snapshots erkennen

Ein DOM-Knoten kann nur dann automatisch bereinigt werden, wenn weder in der DOM-Baumstruktur noch im JavaScript-Code der Seite darauf verwiesen wird. Ein Knoten gilt als "getrennt", wenn er aus der DOM-Struktur entfernt wird, aber JavaScript immer noch auf ihn verweist. Getrennte DOM-Knoten sind eine häufige Ursache von Speicherlecks. In diesem Abschnitt erfahren Sie, wie Sie mit den Heap-Profilern der Entwicklertools getrennte Knoten identifizieren.

Hier sehen Sie ein einfaches Beispiel für getrennte DOM-Knoten.

var detachedTree;

function create() {
  var ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

Durch Klicken auf die im Code referenzierte Schaltfläche wird ein ul-Knoten mit zehn untergeordneten li-Elementen erstellt. Auf diese Knoten wird im Code verwiesen, sie sind jedoch nicht in der DOM-Baumstruktur vorhanden und werden daher getrennt.

Heap-Snapshots sind eine Möglichkeit, getrennte Knoten zu identifizieren. Wie der Name schon sagt, zeigen Heap-Snapshots, wie der Arbeitsspeicher zum Zeitpunkt des Snapshots auf die JS-Objekte und DOM-Knoten Ihrer Seite verteilt ist.

Öffnen Sie zum Erstellen eines Snapshots die Entwicklertools, wählen Sie im Bereich Arbeitsspeicher das Optionsfeld Heap-Snapshot aus und klicken Sie auf die Schaltfläche Snapshot erstellen.

Heap-Snapshot erstellen

Die Verarbeitung und das Laden des Snapshots können einige Zeit in Anspruch nehmen. Wenn er abgeschlossen ist, wählen Sie ihn im linken Bereich (mit dem Namen HEAP SNAPSHOTS) aus.

Geben Sie Detached in das Textfeld Klassenfilter ein, um nach getrennten DOM-Baumstrukturen zu suchen.

Filtern nach getrennten Knoten

Erweitern Sie die Zeichensätze, um einen getrennten Baum zu untersuchen.

Untersuchung eines getrennten Baums

Gelb hervorgehobene Knoten haben direkte Verweise auf sie aus dem JavaScript-Code. Rot hervorgehobene Knoten haben keine direkten Verweise. Sie leben nur, weil sie Teil des gelben Knotenbaums sind. Im Allgemeinen sollten Sie sich auf die gelben Knoten konzentrieren. Korrigieren Sie Ihren Code so, dass der gelbe Knoten nicht länger aktiv ist, als erforderlich ist. Außerdem entfernen Sie die roten Knoten, die Teil des gelben Knotenbaums sind.

Klicken Sie auf einen gelben Knoten, um die Angelegenheit genauer zu untersuchen. Im Bereich Objekte sehen Sie weitere Informationen zu dem Code, der darauf verweist. Im folgenden Screenshot sehen Sie beispielsweise, dass die Variable detachedTree auf den Knoten verweist. Um dieses spezielle Speicherleck zu beheben, prüfen Sie den Code, der detachedTree verwendet, und sorgen Sie dafür, dass der Verweis auf den Knoten entfernt wird, wenn er nicht mehr benötigt wird.

Untersuchung eines gelben Knotens

JS-Heap-Speicherlecks mithilfe von Zuweisungs-Zeitachsen erkennen

Die Zeitleiste für die Zuweisung ist ein weiteres Tool, mit dem Sie Speicherlecks in Ihrem JS-Heap aufspüren können.

Sehen Sie sich zum Veranschaulichen der Zuweisungszeitachse den folgenden Code an:

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Jedes Mal, wenn die im Code referenzierte Schaltfläche gedrückt wird, wird eine Zeichenfolge von einer Million Zeichen in das Array x eingefügt.

Öffnen Sie zum Aufzeichnen einer Zuweisungszeitachse die Entwicklertools, gehen Sie zum Bereich Profile, wählen Sie das Optionsfeld Zuordnungszeitachse aufzeichnen aus, klicken Sie auf die Schaltfläche Start, führen Sie die Aktion aus, die Ihrer Meinung nach das Speicherleck verursacht hat, und drücken Sie dann die Schaltfläche Aufzeichnung beenden (Schaltfläche zum Beenden der Aufzeichnung), wenn Sie fertig sind.

Achten Sie während der Aufzeichnung darauf, ob auf der Zuweisungszeitachse blaue Balken angezeigt werden (siehe Screenshot unten).

neue Zuweisungen

Diese blauen Balken stellen neue Arbeitsspeicherzuweisungen dar. Diese neuen Speicherzuweisungen eignen sich als Kandidaten für Speicherlecks. Sie können einen Balken zoomen, um den Konstruktor-Bereich so zu filtern, dass nur Objekte angezeigt werden, die während des angegebenen Zeitraums zugewiesen wurden.

Vergrößerte Zeitachse für die Zuweisung

Maximieren Sie das Objekt und klicken Sie auf seinen Wert, um weitere Details im Bereich Objekt aufzurufen. Im folgenden Screenshot sehen Sie beispielsweise, wenn Sie die Details des neu zugewiesenen Objekts aufrufen, um zu sehen, dass es der Variablen x im Bereich Window zugewiesen wurde.

Objektdetails

Arbeitsspeicherzuweisung nach Funktion untersuchen

Verwenden Sie den Typ Allocation Sampling im Bereich Arbeitsspeicher, um die Arbeitsspeicherzuweisung nach JavaScript-Funktion anzusehen.

Datensatzzuweisungs-Profiler

  1. Wählen Sie das Optionsfeld Allocation Sampling aus. Wenn sich auf der Seite ein Worker befindet, können Sie diesen im Drop-down-Menü neben der Schaltfläche Start als Profilerstellungsziel auswählen.
  2. Klicken Sie auf Start.
  3. Führen Sie auf der Seite, die Sie untersuchen möchten, die Aktionen aus.
  4. Drücke die Schaltfläche Stopp, wenn du alle Aktionen beendet hast.

Entwicklertools bieten eine Aufschlüsselung der Arbeitsspeicherzuweisung nach Funktion. Die Standardansicht ist Heavy (Bottom-up). Hier werden die Funktionen angezeigt, die oben den meisten Arbeitsspeicher zugewiesen haben.

Zuweisungsprofil

Häufige automatische Speicherbereinigungen ermitteln

Wenn Ihre Seite häufig pausiert wird, liegt möglicherweise ein Problem mit der automatischen Speicherbereinigung vor.

Sie können entweder den Task-Manager von Chrome oder die Aufzeichnung des Zeitachsenspeichers verwenden, um häufige Speicherbereinigungen zu erkennen. Im Task-Manager stellen häufig zunehmende und abnehmende Werte für Memory oder JavaScript Memory eine häufige automatische Speicherbereinigung dar. In Zeitachsenaufzeichnungen deuten Diagramme mit häufig steigenden und abnehmenden JS-Heap- oder Knotenzahlen auf häufige Speicherbereinigungen hin.

Sobald Sie das Problem identifiziert haben, können Sie mithilfe einer Aufzeichnung der Zeitachse herausfinden, wo Speicher zugewiesen wird und welche Funktionen die Zuweisungen verursachen.