Leer hoe je Chrome en DevTools gebruikt om geheugenproblemen te vinden die de paginaprestaties beïnvloeden, waaronder geheugenlekken, geheugenbloat en frequente garbage collection.
Overzicht
- Ontdek hoeveel geheugen je pagina gebruikt met Chrome Taakbeheer.
- Visualiseer het geheugengebruik in de loop van de tijd met tijdlijn-opnamen.
- Identificeer losgekoppelde DOM-boomstructuren (een veelvoorkomende oorzaak van geheugenlekken) met momentopnamen van heap.
- Ontdek wanneer er nieuw geheugen wordt toegewezen in je JS-heap met opnamen van de toewijzingstijdlijn.
- Losstaande elementen herkennen die worden bewaard door een JavaScript-referentie.
Overzicht
In de geest van het RAIL-prestatiemodel moet de focus van je prestatie-inspanningen liggen op je gebruikers.
Geheugenproblemen zijn belangrijk omdat ze vaak merkbaar 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. Een geheugenlek is wanneer een bug op de pagina ervoor zorgt dat de pagina in de loop van de tijd steeds meer geheugen gebruikt.
- De prestaties van een pagina zijn consistent slecht. Dit is mogelijk een symptoom van geheugenbloat. Geheugenbloat is wanneer een pagina meer geheugen gebruikt dan nodig is voor een optimale paginasnelheid.
- De prestaties van een pagina zijn vertraagd of lijken vaak te worden onderbroken. Dit is mogelijk een symptoom van frequente garbage collection. Garbage collection is wanneer de browser geheugen terugvordert. De browser bepaalt wanneer dit gebeurt. Tijdens verzamelingen wordt de uitvoering van alle scripts onderbroken. Als de browser dus veel garbage collection uitvoert, wordt de uitvoering van het script vaak onderbroken.
Geheugenbloat: hoeveel is 'te veel'?
Een geheugenlek is makkelijk te definiëren. Als een site steeds meer geheugen gebruikt, is er sprake van een lek. Maar geheugenbloat is wat moeilijker vast te stellen. Wat valt onder 'te veel geheugen gebruiken'?
Er zijn geen harde cijfers, omdat verschillende apparaten en browsers verschillende mogelijkheden hebben. Dezelfde pagina die soepel werkt op een geavanceerde smartphone, kan crashen op een minder geavanceerde smartphone.
Het is belangrijk dat je het RAIL-model gebruikt en je op je gebruikers richt. Ontdek welke apparaten populair zijn bij je gebruikers en test je pagina op die apparaten. Als de functionaliteit consistent slecht is, overschrijdt de pagina misschien de geheugencapaciteit van die apparaten.
Het geheugengebruik in realtime bijhouden met Taakbeheer van Chrome
Gebruik Chrome Taakbeheer als startpunt voor je onderzoek naar geheugenproblemen. Taakbeheer is een realtime monitor die aangeeft hoeveel geheugen een pagina gebruikt.
Druk op Shift+Esc of ga naar het hoofdmenu van Chrome en selecteer Meer tools > Taakbeheer om Taakbeheer te openen.

Klik met de rechtermuisknop op de tabelkop van Taakbeheer en zet JavaScript-geheugen aan.

Deze 2 kolommen geven verschillende informatie over hoe je pagina geheugen gebruikt:
- De kolom Geheugenverbruik staat voor OS-geheugen. DOM-nodes worden opgeslagen in het OS-geheugen. Als deze waarde toeneemt, worden er DOM-nodes gemaakt.
De kolom JavaScript-geheugen vertegenwoordigt de JS-heap. Deze kolom bevat 2 waarden. De waarde waarin je geïnteresseerd bent, is het live aantal (het getal tussen haakjes). Het live getal geeft aan hoeveel geheugen de bereikbare objecten op je pagina gebruiken. Als dit aantal toeneemt, worden er nieuwe objecten gemaakt of worden de bestaande objecten groter.

Geheugenlekken visualiseren met prestatie-opnamen
Je kunt het deelvenster Prestaties ook gebruiken als een ander startpunt voor je onderzoek. In het deelvenster Prestaties kun je het geheugengebruik van een pagina in de loop van de tijd visualiseren.
- Open het deelvenster Prestaties in DevTools.
- Vink het selectievakje Geheugen aan.
- Maak een opname.
Overweeg de volgende code om geheugenopnamen van Prestaties 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 er tienduizend div-nodes toegevoegd aan de documenthoofdtekst en wordt een tekenreeks van een miljoen x-tekens naar de x-matrix gepusht.
Als je deze code uitvoert, wordt er een tijdlijnopname gemaakt zoals in het volgende screenshot:

Eerst een uitleg van de gebruikersinterface. Het diagram HEAP in het deelvenster Overzicht (onder NET) vertegenwoordigt de JS-heap. Onder het deelvenster Overzicht staat het deelvenster Teller. Hier kun je het geheugengebruik zien, uitgesplitst naar JS-heap (hetzelfde als het diagram HEAP in het deelvenster Overzicht), documenten, DOM-nodes, listeners en GPU-geheugen. Als je een selectievakje uitzet, wordt het verborgen in het diagram.
Nu een analyse van de code vergeleken met het screenshot. Als je naar de knooppuntteller (het groene diagram) kijkt, zie je dat deze overeenkomt met de code. Het aantal nodes neemt toe in
discrete stappen. Je kunt ervan uitgaan dat elke toename van het aantal nodes een aanroep naar grow() is. Het JS-heapdiagram (het blauwe diagram) is niet zo eenvoudig. In overeenstemming met best practices is de eerste daling eigenlijk een geforceerde garbage collection (bereikt door op de knop Garbage collection te drukken). Naarmate de opname vordert, zie je dat de JS-heapgrootte piekt. Dit is natuurlijk en verwacht: de JavaScript-code maakt de DOM-nodes bij elke klik op de knop en doet veel werk als de tekenreeks van een miljoen tekens wordt gemaakt. Het belangrijkste hier is dat de JS-heap hoger eindigt dan deze begon (het 'begin' is hier het punt na de geforceerde garbagecollection). In de echte wereld zou dit patroon van toenemende JS-heapgrootte of knooppuntgrootte mogelijk een geheugenlek betekenen.
Geheugenlekken in losgekoppelde DOM-boomstructuren ontdekken met momentopnamen van heap
Een DOM-node kan alleen worden opgeruimd als er geen verwijzingen naar zijn vanuit de DOM-boomstructuur of JavaScript-code van de pagina. Een node wordt 'losgekoppeld' genoemd als deze uit de DOM-boomstructuur wordt verwijderd, maar er nog steeds naar wordt verwezen door JavaScript. Losgekoppelde DOM-nodes zijn een veelvoorkomende oorzaak van geheugenlekken. In dit gedeelte leer je hoe je de heapprofilers van DevTools gebruikt 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 je op de knop klikt waarnaar in de code wordt verwezen, wordt er een ul-node met 10 onderliggende li-elementen gemaakt. De code verwijst naar deze nodes, maar ze bestaan niet in de DOM-boomstructuur. Daarom zijn ze losgekoppeld.
Momentopnamen van heap zijn een manier om losgekoppelde nodes te identificeren. Zoals de naam al aangeeft, tonen momentopnamen van heap hoe het geheugen is verdeeld over de JS-objecten en DOM-nodes van je pagina op het moment van de momentopname.
Als je een momentopname wilt maken, open je DevTools en ga je naar het deelvenster Geheugen. Selecteer het keuzerondje Momentopname van heap en druk op de knop Momentopname maken.

Het kan even duren voordat de momentopname is verwerkt en geladen. Als de momentopname klaar is, selecteer je deze in het linkerdeelvenster (met de naam Momentopnamen van heap).
Typ Detached in het invoervak Klassefilter om te zoeken naar losgekoppelde DOM-boomstructuren.

Vouw de dakjes uit om een losgekoppelde boom te onderzoeken.

Klik op een knooppunt om het verder te onderzoeken. In het deelvenster Objecten vind je meer informatie over de code die ernaar verwijst. In het volgende screenshot zie je bijvoorbeeld dat de variabele detachedTree verwijst naar de node. Als je dit specifieke geheugenlek wilt oplossen, bestudeer je de code die detachedTree gebruikt en zorg je dat de verwijzing naar de node wordt verwijderd als deze niet meer nodig is.

JS-heapgeheugenlekken identificeren met toewijzingstijdlijnen
De toewijzingstijdlijn is een andere tool waarmee je geheugenlekken in je JS-heap kunt opsporen.
Bekijk de volgende code om de toewijzingstijdlijn te demonstreren:
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 tekenreeks van 1 miljoen tekens toegevoegd aan de x-matrix.
Als je een toewijzingstijdlijn wilt opnemen, open je DevTools, ga je naar het deelvenster Geheugen, selecteer je het keuzerondje Toewijzingen op tijdlijn, druk je op de knop Opnemen, voer je de actie uit waarvan je vermoedt dat deze het geheugenlek veroorzaakt en druk je op de knop Opname stoppen als je klaar bent.
Let tijdens de opname op of er blauwe balken verschijnen op de toewijzingstijdlijn, zoals in het volgende screenshot.

Die blauwe balken staan voor nieuwe geheugentoewijzingen. Die nieuwe geheugentoewijzingen zijn je kandidaten voor geheugenlekken. Je kunt inzoomen op een balk om het deelvenster Constructor te filteren, zodat alleen objecten worden getoond die zijn toegewezen tijdens het aangegeven tijdsbestek.

Vouw het object uit en klik op de waarde om meer informatie te bekijken in het deelvenster Object. In het onderstaande screenshot kun je bijvoorbeeld zien dat het object is toegewezen aan de variabele x in het bereik Window door de details van het nieuw toegewezen object te bekijken.

Geheugentoewijzing per functie onderzoeken
Gebruik het profieltype Toewijzingssteekproef in het deelvenster Geheugen om de geheugentoewijzing per JavaScript-functie te bekijken.

- Selecteer het keuzerondje Toewijzingssteekproef. Als er een worker op de pagina staat, kun je die selecteren als profileringsdoel in het venster JavaScript VM-instantie selecteren.
- Druk op de knop Starten.
- Voer de acties uit op de pagina die je wilt onderzoeken.
- Druk op de knop Stoppen als je klaar bent met alle acties.
DevTools toont een uitsplitsing van de geheugentoewijzing per functie. De standaardweergave is Zwaar (van onder naar boven). Hierbij worden de functies die het meeste geheugen hebben toegewezen bovenaan weergegeven.

Objecten identificeren die worden bewaard door een JS-referentie
Het profiel Losstaande elementen toont losstaande elementen die blijven bestaan omdat er naar wordt verwezen door JavaScript-code.
Neem een profiel voor Losgekoppelde elementen op om de exacte HTML-nodes en het aantal nodes te bekijken.

Frequente garbage collections opsporen
Als je pagina vaak lijkt te pauzeren, heb je misschien problemen met garbage collection.
Je kunt de Chrome-taakbeheerder of tijdlijn-geheugenopnamen gebruiken om frequente garbage collection te herkennen. In Taakbeheer vertegenwoordigen vaak stijgende en dalende waarden voor Geheugen of JavaScript-geheugen frequente garbage collections. In tijdlijn-opnamen geven vaak stijgende en dalende JS-heap- of node-telling-diagrammen frequente garbage collections aan.
Nadat je het probleem hebt vastgesteld, kun je een opname van de toewijzingstijdlijn gebruiken om te achterhalen waar geheugen wordt toegewezen en welke functies de toewijzingen veroorzaken.