Geheugenproblemen oplossen

Leer hoe u Chrome en DevTools kunt gebruiken om geheugenproblemen op te sporen die de prestaties van de pagina beïnvloeden, waaronder geheugenlekken, geheugenophoping en frequente ophaalacties.

Samenvatting

  • Ontdek hoeveel geheugen uw pagina momenteel gebruikt met Chrome Taakbeheer.
  • Visualiseer het geheugengebruik in de loop van de tijd met tijdlijnopnamen.
  • Identificeer losstaande DOM-bomen (een veelvoorkomende oorzaak van geheugenlekken) met Heap Snapshots.
  • Ontdek wanneer er nieuw geheugen wordt toegewezen in uw JS-heap met toewijzingstijdlijnopnamen.

Overzicht

In de geest van het RAIL- prestatiemodel moet de focus van uw prestatie-inspanningen liggen op uw gebruikers.

Geheugenproblemen zijn belangrijk omdat ze vaak waarneembaar zijn voor gebruikers. Gebruikers kunnen geheugenproblemen op de volgende manieren waarnemen:

  • De prestaties van een pagina worden in de loop van de tijd steeds slechter. Dit is mogelijk een symptoom van een geheugenlek. Er is sprake van een geheugenlek als een bug op de pagina ervoor zorgt dat de pagina in de loop van de tijd steeds meer geheugen gaat gebruiken.
  • De prestaties van een pagina zijn voortdurend slecht. Dit is mogelijk een symptoom van een opgeblazen geheugen. Er is sprake van geheugenophoping wanneer een pagina meer geheugen gebruikt dan nodig is voor een optimale paginasnelheid.
  • De prestaties van een pagina zijn vertraagd of lijken regelmatig te pauzeren. Dit is mogelijk een symptoom van frequente afvalinzameling. Garbage collection is wanneer de browser geheugen terugwint. De browser bepaalt wanneer dit gebeurt. Tijdens verzamelingen wordt alle uitvoering van scripts onderbroken. Dus als de browser veel afval verzamelt, zal de uitvoering van het script vaak worden gepauzeerd.

Geheugenopgeblazen gevoel: hoeveel is "te veel"?

Een geheugenlek is eenvoudig te definiëren. Als een site steeds meer geheugen gebruikt, is er sprake van een lek. Maar geheugenzwelling is iets moeilijker vast te stellen. Wat kwalificeert als "te veel geheugen gebruiken"?

Hier zijn geen harde cijfers voor, omdat verschillende apparaten en browsers verschillende mogelijkheden hebben. Dezelfde pagina die soepel draait op een high-end smartphone kan crashen op een low-end smartphone.

De sleutel hier is om het RAIL-model te gebruiken en u te concentreren op uw gebruikers. Ontdek welke apparaten populair zijn bij uw gebruikers en test vervolgens uw pagina op die apparaten. Als de ervaring voortdurend slecht is, overschrijdt de pagina mogelijk de geheugencapaciteit van die apparaten.

Houd het geheugengebruik in realtime in de gaten met Chrome Task Manager

Gebruik Chrome Task Manager als startpunt voor uw onderzoek naar geheugenproblemen. De Task Manager is een realtime monitor die u vertelt hoeveel geheugen een pagina momenteel gebruikt.

  1. Druk op Shift+Esc of ga naar het Chrome-hoofdmenu en selecteer Meer tools > Taakbeheer om Taakbeheer te openen.

    Taakbeheer openen

  2. Klik met de rechtermuisknop op de tabelkop van Taakbeheer en schakel JavaScript-geheugen in.

    JS-geheugen inschakelen

Deze twee kolommen vertellen u verschillende dingen over hoe uw pagina geheugen gebruikt:

  • De kolom Geheugen vertegenwoordigt het eigen geheugen. DOM-knooppunten worden opgeslagen in het eigen geheugen. Als deze waarde toeneemt, worden er DOM-knooppunten gemaakt.
  • De JavaScript-geheugenkolom vertegenwoordigt de JS-heap. Deze kolom bevat twee waarden. De waarde waarin u geïnteresseerd bent, is het live-nummer (het nummer tussen haakjes). Het live-nummer geeft aan hoeveel geheugen de bereikbare objecten op uw pagina gebruiken. Als dit aantal toeneemt, worden er nieuwe objecten gemaakt of groeien de bestaande objecten.

Visualiseer geheugenlekken met prestatie-opnames

U kunt het Prestatiepaneel ook als extra startpunt in uw onderzoek gebruiken. Met het paneel Prestaties kunt u het geheugengebruik van een pagina in de loop van de tijd visualiseren.

  1. Open het prestatiepaneel op DevTools.
  2. Schakel het selectievakje Geheugen in.
  3. Maak een opname .

Bekijk de onderstaande code om prestatiegeheugenopnamen te demonstreren:

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);

Elke keer dat de knop waarnaar in de code wordt verwezen wordt ingedrukt, worden tienduizend div knooppunten aan de documenttekst toegevoegd en wordt een reeks van een miljoen x tekens op de x array geduwd. Het uitvoeren van deze code levert een tijdlijnopname op zoals in de volgende schermafbeelding:

eenvoudig groeivoorbeeld

Eerst een uitleg van de gebruikersinterface. De HEAP- grafiek in het overzichtsvenster (onder NET ) vertegenwoordigt de JS-heap. Onder het overzichtsvenster bevindt zich het tellervenster . Hier ziet u het geheugengebruik uitgesplitst naar JS-heap (hetzelfde als de HEAP- grafiek in het overzichtspaneel ), documenten, DOM-knooppunten, luisteraars en GPU-geheugen. Als u een selectievakje uitschakelt, wordt het verborgen in de grafiek.

Nu een analyse van de code vergeleken met de schermafbeelding. Als je naar de knooppuntteller (de groene grafiek) kijkt, kun je zien dat deze netjes overeenkomt met de code. Het aantal knooppunten neemt in discrete stappen toe. Je kunt ervan uitgaan dat elke toename van het aantal knooppunten een aanroep is voor grow() . De JS-heapgrafiek (de blauwe grafiek) is niet zo eenvoudig. In overeenstemming met de beste praktijken is de eerste dip eigenlijk een gedwongen afvalophaling (behaald door op de knop afval verzamelen te drukken). Naarmate de opname vordert, kun je zien dat de JS-heapgrootte toeneemt. Dit is natuurlijk en te verwachten: de JavaScript-code creëert de DOM-knooppunten bij elke klik op een knop en doet veel werk wanneer het de reeks van een miljoen tekens creëert. Het belangrijkste hier is het feit dat de JS-heap hoger eindigt dan hij begon (het "begin" is hier het punt na de gedwongen afvalinzameling). Als je dit patroon van toenemende JS-heapgrootte of knooppuntgrootte in de echte wereld zou zien, zou dit mogelijk een geheugenlek betekenen.

Ontdek losstaande DOM-boomgeheugenlekken met Heap Snapshots

Een DOM-knooppunt kan alleen worden verzameld als er geen verwijzingen naar zijn vanuit de DOM-boom van de pagina of vanuit JavaScript-code. Er wordt gezegd dat een knooppunt "losgekoppeld" is wanneer het uit de DOM-structuur wordt verwijderd, maar sommige JavaScripts verwijzen er nog steeds naar. Losstaande DOM-knooppunten zijn een veelvoorkomende oorzaak van geheugenlekken. In deze sectie leert u hoe u de heap profilers van DevTools kunt gebruiken om losgemaakte knooppunten te identificeren.

Hier is een eenvoudig voorbeeld van vrijstaande DOM-knooppunten.

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);

Als u op de knop klikt waarnaar in de code wordt verwezen, wordt een ul knooppunt met tien li kinderen gemaakt. Naar deze knooppunten wordt in de code verwezen, maar ze bestaan ​​niet in de DOM-structuur, dus ze zijn losgekoppeld.

Heap-snapshots zijn een manier om losgemaakte knooppunten te identificeren. Zoals de naam al aangeeft, laten heap-snapshots zien hoe het geheugen is verdeeld over de JS-objecten en DOM-knooppunten van uw pagina op het tijdstip van de momentopname.

Om een ​​momentopname te maken, opent u DevTools en gaat u naar het paneel Geheugen , selecteert u het keuzerondje Heap Snapshot en drukt u vervolgens op de knop Momentopname maken .

een heap-snapshot maken

Het verwerken en laden van de momentopname kan enige tijd duren. Zodra het klaar is, selecteert u het in het linkerpaneel (genaamd HEAP SNAPSHOTS ).

Typ Detached in het tekstvak Klassefilter om te zoeken naar vrijstaande DOM-bomen.

filteren op losgemaakte knooppunten

Vouw de karaat uit om een ​​vrijstaande boom te onderzoeken.

onderzoek naar losse boom

Geel gemarkeerde knooppunten hebben directe verwijzingen ernaar vanuit de JavaScript-code. Rood gemarkeerde knooppunten hebben geen directe referenties. Ze leven alleen omdat ze deel uitmaken van de boom van de gele knoop. Over het algemeen wilt u zich concentreren op de gele knooppunten. Corrigeer je code zodat het gele knooppunt niet langer leeft dan nodig is, en verwijder ook de rode knooppunten die deel uitmaken van de boom van het gele knooppunt.

Klik op een geel knooppunt om dit verder te onderzoeken. In het deelvenster Objecten ziet u meer informatie over de code die ernaar verwijst. In de onderstaande schermafbeelding kunt u bijvoorbeeld zien dat de variabele detachedTree verwijst naar het knooppunt. Om dit specifieke geheugenlek te verhelpen, zou je de code die detachedTree gebruikt, moeten bestuderen en ervoor zorgen dat de verwijzing naar het knooppunt wordt verwijderd wanneer deze niet langer nodig is.

onderzoek naar een gele knoop

Identificeer JS-heapgeheugenlekken met toewijzingstijdlijnen

De Allocation Timeline is een ander hulpmiddel dat u kan helpen geheugenlekken in uw JS-heap op te sporen.

Om de toewijzingstijdlijn te demonstreren, gebruikt u de volgende code:

var x = [];

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

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

Elke keer dat de knop waarnaar in de code wordt verwezen, wordt ingedrukt, wordt een reeks van een miljoen tekens aan de x array toegevoegd.

Om een ​​toewijzingstijdlijn op te nemen, opent u DevTools, gaat u naar het paneel Profielen , selecteert u het keuzerondje Toewijzingstijdlijn opnemen , drukt u op de knop Start , voert u de actie uit waarvan u vermoedt dat deze het geheugenlek veroorzaakt en drukt u vervolgens op de knop Opname stoppen ( knop opname stoppen ) wanneer je klaar bent.

Let tijdens het opnemen op of er blauwe balken verschijnen op de toewijzingstijdlijn, zoals in de onderstaande schermafbeelding.

nieuwe toewijzingen

Die blauwe balken vertegenwoordigen nieuwe geheugentoewijzingen. Deze nieuwe geheugentoewijzingen zijn uw kandidaten voor geheugenlekken. U kunt op een balk inzoomen om het Constructor- venster zo te filteren dat alleen objecten worden weergegeven die tijdens het opgegeven tijdsbestek zijn toegewezen.

ingezoomde toewijzingstijdlijn

Vouw het object uit en klik op de waarde ervan om meer details erover te bekijken in het objectvenster . In de onderstaande schermafbeelding kunt u bijvoorbeeld, door de details te bekijken van het object dat nieuw is toegewezen, zien dat het is toegewezen aan de x variabele in het Window .

objectdetails

Onderzoek geheugentoewijzing per functie

Gebruik het type Allocation Sampling in het paneel Memory om de geheugentoewijzing via de JavaScript-functie te bekijken.

Recordtoewijzingsprofiler

  1. Selecteer het keuzerondje Allocatiebemonstering . Als er een medewerker op de pagina staat, kunt u die selecteren als profileringsdoel via het vervolgkeuzemenu naast de knop Start .
  2. Druk op de Start- knop.
  3. Voer de acties uit op de pagina die u wilt onderzoeken.
  4. Druk op de Stop- knop als u klaar bent met al uw acties.

DevTools toont u een overzicht van de geheugentoewijzing per functie. De standaardweergave is Heavy (Bottom Up) , waarbij bovenaan de functies worden weergegeven die het meeste geheugen hebben toegewezen.

Toewijzingsprofiel

Ontdek frequente afvalophalingen

Als het lijkt alsof uw pagina regelmatig wordt onderbroken, zijn er mogelijk problemen met de afvalinzameling.

U kunt Chrome Task Manager of tijdlijngeheugenopnamen gebruiken om frequente afvalverzamelingen te spotten. In Taakbeheer vertegenwoordigen vaak stijgende en dalende geheugen- of JavaScript-geheugenwaarden frequente afvalverzamelingen. In tijdlijnopnamen duiden frequent stijgende en dalende JS-heap- of knooppunttellinggrafieken op frequente ophaalacties.

Zodra u het probleem heeft geïdentificeerd, kunt u een toewijzingstijdlijnopname gebruiken om uit te zoeken waar geheugen wordt toegewezen en welke functies de toewijzingen veroorzaken.