Geheugenproblemen oplossen

Leer hoe u Chrome en DevTools kunt gebruiken om geheugenproblemen op te sporen die de prestaties van pagina’s beïnvloeden, zoals geheugenlekken, memory bloat en frequente garbage collections.

Summary #

  • Ontdek hoeveel geheugen uw pagina momenteel gebruikt met de Chrome Task Manager.
  • Visualiseer het geheugengebruik in de loop van de tijd met Timeline-opnamen.
  • Identificeer losgekoppelde DOM-bomen (een veelvoorkomende oorzaak van geheugenlekken) met Heap Snapshots.
  • Ontdek wanneer er nieuw geheugen wordt gealloceerd in uw JS-heap met Allocation Timeline-opnamen.

Overzicht #

In de geest van het RAIL-prestatiemodel moeten uw gebruikers de focus van uw prestatie-inspanningen zijn.

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

  • De prestaties van een pagina worden na verloop van tijd steeds slechter. Dit is mogelijk een symptoom van een geheugenlek. Van een geheugenlek is sprake wanneer een bug in de pagina ervoor zorgt dat de pagina in de loop van de tijd steeds meer geheugen gebruikt.
  • De prestaties van een pagina zijn voortdurend slecht. Dit is mogelijk een symptoom van memory bloat. Van memory bloat is sprake wanneer een pagina meer geheugen gebruikt dan nodig is voor een optimale paginasnelheid.
  • De prestaties van een pagina zijn vertraagd of lijken vaak te pauzeren. Dit is mogelijk een symptoom van frequente vuilnisophalingen. Garbage collection is het terughalen van geheugen door de browser. De browser bepaalt wanneer dit gebeurt. Tijdens het ophalen wordt de uitvoering van het script gepauzeerd. Dus als de browser vaak vuilnis ophaalt, wordt de uitvoering van het script vaak gepauzeerd.

Memory bloat: hoeveel is “te veel”?

Een geheugenlek is eenvoudig te definiëren. Als een site steeds meer geheugen gebruikt, dan heb je een lek. Maar geheugenbloat is wat moeilijker te definiëren. Wat is te beschouwen als “te veel geheugen gebruiken”?

Er zijn geen harde cijfers, omdat verschillende apparaten en browsers verschillende mogelijkheden hebben. Dezelfde pagina die probleemloos werkt op een high-end smartphone kan crashen op een low-end smartphone.

De sleutel hier is om het RAIL-model te gebruiken en je te richten op je gebruikers. Zoek uit welke apparaten populair zijn bij uw gebruikers, en test vervolgens uw pagina op die apparaten. Als de ervaring consistent slecht is, overschrijdt de pagina mogelijk de geheugencapaciteiten van die apparaten.

Monitor geheugengebruik in realtime met de Chrome Task Manager #

Gebruik de 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 hoofdmenu van Chrome en selecteer Meer tools > Task manager om de Task Manager te openen.

    Openen van Taakbeheer

  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 staat voor native geheugen. DOM-nodes worden opgeslagen in het eigen geheugen. Als deze waarde toeneemt, worden er DOM-nodes aangemaakt.
  • De JavaScript-geheugenkolom vertegenwoordigt de JS-heap. Deze kolom bevat twee waarden. De waarde waarin je geïnteresseerd bent is het live-getal (het getal tussen haakjes). Het live-getal geeft aan hoeveel geheugen de bereikbare objecten op je pagina gebruiken. Als dit getal toeneemt, worden er ofwel nieuwe objecten aangemaakt, ofwel groeien de bestaande objecten.

Visualiseer geheugenlekken met Timeline-opnamen #

Je kunt het Timeline-paneel ook gebruiken als een ander startpunt in je onderzoek. Het Timeline-paneel helpt je het geheugengebruik van een pagina in de loop van de tijd te visualiseren.

  1. Open het Timeline-paneel in DevTools.
  2. Schakel het selectievakje Geheugen in.
  3. Maak een opname.
    1. Tip: Het is een goede gewoonte om je opname te beginnen en te eindigen met een geforceerde garbage collection. Klik op de collect garbage-knop (force garbage collection button) tijdens het opnemen om garbage collection te forceren.

      Om Timeline-geheugenopnamen te demonstreren, bekijk de onderstaande code eens:

      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 nodes aan de document body toegevoegd, en een string van een miljoen x karakters wordt in de x array geduwd. Het uitvoeren van deze code levert een Timeline-opname op zoals de volgende schermafbeelding:

      simpel groeivoorbeeld

      Eerst een uitleg van de gebruikersinterface. De HEAP-grafiek in het deelvenster Overzicht (onder NET) geeft de JS-heap weer. Onder het deelvenster Overzicht bevindt zich het deelvenster Teller. Hier kunt u het geheugengebruik zien uitgesplitst naar JS heap (hetzelfde als de HEAP grafiek in het Overview deelvenster), documenten, DOM nodes, listeners, en GPU geheugen. Het uitschakelen van een selectievakje verbergt het uit de grafiek.

      Nu, een analyse van de code vergeleken met de schermafbeelding. Als je naar de knooppuntenteller kijkt (de groene grafiek), zie je dat die netjes overeenkomt met de code. Het aantal knooppunten neemt in discrete stappen toe. Je kunt ervan uitgaan dat elke toename in het aantal node’s een oproep is aan grow(). De JS heap grafiek (de blauwe grafiek) is niet zo rechtlijnig. In overeenstemming met de beste praktijken, is de eerste dip eigenlijk een geforceerde afvalverzameling (bereikt door op de collect garbage knop te drukken). Naarmate de opname vordert kun je zien dat de JS heap grootte een piek vertoont. Dit is natuurlijk en te verwachten: de JavaScript code maakt de DOM nodes bij elke klik op de knop en doet veel werk bij het maken van de string van een miljoen karakters. Het belangrijkste hier is het feit dat de JS heap hoger eindigt dan hij begon (het “begin” hier is het punt na de gedwongen vuilnisophaling). In de echte wereld, als je dit patroon van toenemende JS heap grootte of node grootte zou zien, zou het mogelijk een geheugenlek betekenen.

      Ontdek losstaande DOM tree geheugenlekken met Heap Snapshots #

      Een DOM node kan alleen worden vuilgemaakt als er geen verwijzingen naar zijn vanuit de pagina’s DOM tree of JavaScript code. Een node wordt “onthecht” genoemd als hij uit de DOM-structuur is verwijderd, maar er nog wel verwijzingen naar zijn in JavaScript. Losgekoppelde DOM-nodes zijn een veel voorkomende oorzaak van geheugenlekken. Dit gedeelte leert u hoe u DevTools’ heap profilers kunt gebruiken om losgekoppelde nodes te identificeren.

      Hier volgt een eenvoudig voorbeeld van losgekoppelde DOM nodes.

      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 node gemaakt met tien li kinderen. Naar deze nodes wordt door de code verwezen, maar ze bestaan niet in de DOM-boom, dus zijn ze onthecht.

      Heap snapshots zijn een manier om onthechte nodes te identificeren. Zoals de naam al aangeeft, laten heap snapshots zien hoe het geheugen is verdeeld over de JS-objecten en DOM-knooppunten op de pagina op het moment dat de snapshot wordt gemaakt.

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

      take heap snapshot

      Het kan enige tijd duren voordat de momentopname is verwerkt en geladen. Als hij klaar is, selecteert u hem in het linkerpaneel (genaamd HEAP SNAPSHOTS).

      Type Detached in het klassefiltertekstvak om te zoeken naar losstaande DOM-bomen.

      filter op losstaande nodes

      Breid de karaten uit om een losstaande boom te onderzoeken.

      onderzoek naar losstaande boom

      Geel gemarkeerde nodes hebben directe verwijzingen ernaar vanuit de JavaScript-code. Rood gemarkeerde knooppunten hebben geen directe verwijzingen. Ze zijn alleen levend omdat ze deel uitmaken van de gele boomstructuur van de node. In het algemeen wil je je concentreren op de gele nodes. Herstel je code zodat de gele node niet langer in leven is dan nodig is, en je verwijdert ook de rode nodes die deel uitmaken van de boom van de gele node.

      Klik op een gele node om hem verder te onderzoeken. In het Objects-paneel kunt u meer informatie zien over de code die ernaar verwijst. In de schermafbeelding hieronder kunt u bijvoorbeeld zien dat de variabele detachedTree naar de node verwijst. Om dit geheugenlek op te lossen, moet je de code die detachedTree gebruikt bestuderen en ervoor zorgen dat de verwijzing naar de node wordt verwijderd als deze niet langer nodig is.

      onderzoek een gele node

      Identificeer JS heap geheugenlekken met Allocatietijdlijnen #

      De Allocatietijdlijn is een ander hulpmiddel waarmee u geheugenlekken in uw JS heap kunt opsporen.

      Om de Allocation Timeline te demonstreren, beschouw je 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 string van een miljoen tekens toegevoegd aan de x array.

      Om een toewijzingstimeline op te nemen, open DevTools, ga naar het paneel Profielen, selecteer het keuzerondje Opnemen toewijzingstimeline, druk op de startknop, voer de actie uit waarvan je vermoedt dat die het geheugenlek veroorzaakt, en druk vervolgens op de stop-opnameknop (stop-opnameknop) als je klaar bent.

      Terwijl u aan het opnemen bent, kunt u zien of er blauwe balken op de toewijzingstijdlijn verschijnen, zoals in de schermafbeelding hieronder.

      nieuwe toewijzingen

      Deze blauwe balken staan voor nieuwe geheugentoewijzingen. Deze nieuwe geheugentoewijzingen zijn uw kandidaten voor geheugenlekken. U kunt op een balk inzoomen om het deelvenster Constructor te filteren en alleen objecten weer te geven die tijdens het opgegeven tijdsbestek zijn toegewezen.

      gezoomde toewijzingstijdlijn

      Uitbreid het object uit en klik op de waarde om meer details over het object weer te geven in het deelvenster Object. In de schermafbeelding hieronder kun je bijvoorbeeld zien dat het object is toegewezen aan de variabele x in het bereik Window, door de details te bekijken van het object dat onlangs is toegewezen.

      objectdetails

      Geheugentoewijzing per functie onderzoeken #

      Gebruik het type Record Allocation Profiler om de geheugentoewijzing per JavaScript-functie te bekijken.

      Record Allocation Profiler

      1. Selecteer het keuzerondje Record Allocation Profiler. Als er een werker op de pagina is, kunt u die selecteren als het profileringsdoel met het vervolgkeuzemenu naast de Start-knop.
      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 uitsplitsing van de geheugentoewijzing per functie. De standaardweergave is Heavy (Bottom Up), waarbij de functies die het meeste geheugen hebben toegewezen bovenaan worden weergegeven.

      Toewijzingsprofiel

      Spot frequente vuilnisverzamelingen #

      Als uw pagina vaak lijkt te pauzeren, hebt u mogelijk problemen met de vuilnisverzameling.

      U kunt de taakbeheerder van Chrome of geheugenregistraties op de tijdlijn gebruiken om frequente vuilnisverzamelingen te spotten. In Taakbeheer wijzen vaak stijgende en dalende waarden van het geheugen of JavaScript-geheugen op frequente afvalverzamelingen. In Timeline-opnamen wijzen vaak stijgende en dalende JS-heap- of node-tellinggrafieken op frequente afvalverzamelingen.

      Als u het probleem eenmaal hebt geïdentificeerd, kunt u een Allocation Timeline-opname gebruiken om erachter te komen waar geheugen wordt toegewezen en welke functies de toewijzingen veroorzaken.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *