Finding and debugging memory leaks in JavaScript with Chrome DevTools

61
Finding and debugging memory leaks in JavaScript with Chrome DevTools

description

JavaScript applications are increasingly larger and they also tend to execute during longer periods. In these applications, the memory is a scarce and valuable resource that must be taken care of. With the support of the Chrome Dev Tools, we will learn how to analyze memory consumption and how to find and fix memory leaks, making our applications more stable and robust in the way.

Transcript of Finding and debugging memory leaks in JavaScript with Chrome DevTools

Page 1: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Findinganddebugging

memoryleaksinJavaScriptwith

ChromeDevTools

Page 2: Finding and debugging memory leaks in JavaScript with Chrome DevTools

GonzaloRuizdeVilla@gruizdevilla

Ico-founded&work@adesis

Thispresentationwasmakeformyworkshopat#spainjs2013

$whoami

$aboutthis

Page 3: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Whatisamemoryleak?

Page 4: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Graduallossofavailablecomputermemory

whenaprogramrepeatedly

failstoreturnmemorythatithasobtainedfortemporaryuse.

Page 5: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Myusershavelaptopswith16GBofRAM.

So,whyshouldIcare?

Page 6: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Commonbelief

Morememory===Betterperformance

Page 7: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Reality

Memoryfootprint

isstronglycorrelatedwith

increasedlatenciesandvariance

Page 8: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Nothingisfree:

(cheaporexpensive)

youwillalwayspayapricefortheresourcesyouuse

Page 9: Finding and debugging memory leaks in JavaScript with Chrome DevTools

So,let'stalkaboutmemory

Page 10: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Thinkofmemoryasagraph

Page 11: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Threeprimitivetypes:

Numbers(e.g,3.14159...)Booleans(trueorfalse)

Strings(e.g,"WernerHeisenberg")

Theycannotreferenceothervalues.Theyarealwaysleafsorterminatingnodes.

Page 12: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Everythingelseisan"Object"

Objectsareassociativearrays(mapsordictionaries)

So,theobjectiscomposedofacollectionof(key,value)pairs

Page 13: Finding and debugging memory leaks in JavaScript with Chrome DevTools

AndwhataboutArrays?

AnArrayisanObjectwithnumerickeys.

Page 14: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Thememorygraphstartswitharoot

Itmaybethe objectofthebrowser,orthe objectofaNode.jsmodule.

windowGlobalYoudon'tcontrolhowthisrootobjectisGC

Page 15: Finding and debugging memory leaks in JavaScript with Chrome DevTools

WhatdoesgetGC?Whateverisnotreachablefromtheroot.

Page 16: Finding and debugging memory leaks in JavaScript with Chrome DevTools

RetainingpathWecallaretainingpathanypathfromGCrootstoaparticularobject

Page 17: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Dominators

Node1dominatesnode2Node2dominatesnodes3,4and6Node3dominatesnode5Node5dominatesnode8Node6dominatesnode7

Page 18: Finding and debugging memory leaks in JavaScript with Chrome DevTools

SomefactsabouttheV8GarbageCollector

Page 19: Finding and debugging memory leaks in JavaScript with Chrome DevTools

GenerationalCollector

Ageofavalue

YoungGeneration

OldGeneration

Theageofavalue:numberofbytesallocatedsinceitwasallocated.

Splitedintwospaces:named"to"and"from""tospace":veryfastallocationfillingthe"tospace"triggersacollection:

"to"and"from"swapmaybepromotiontooldgeneration~10ms(remember60fps->~16ms)

Oldgenerationcollectionisslow.

Page 20: Finding and debugging memory leaks in JavaScript with Chrome DevTools

"To"and"From"spaces

Page 21: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Remember:triggeringa

collectionpausesyourapplication.

Page 22: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Somede-referencecommonerrors

Becarefulwitthedeletekeyword.

"o"becomesanSLOWobject.

varo={x:"y"};deleteo.x;o.x;//undefined

varo={x:"y"};o=null;o.x;//TypeError

Itisbettertoset"null".

Onlywhenthelastreferencetoanobjectisremoved,isthatobjecteligibleforcollection.

Page 23: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Awordon"slow"objectsV8optimizingcompilermakesassumptionsonyourcodetomakeoptimizations.

Ittransparentlycreateshiddenclassesthatrepresentyourobjects.

Usingthishiddenclasses,V8worksmuchfaster.Ifyou"delete"properties,theseassumptionsarenolongervalid,andthecodeisde-optimized,slowingyourcode.

Page 24: Finding and debugging memory leaks in JavaScript with Chrome DevTools

FastObject SlowObject

"slow"shouldbeusingasmallermemoryfootprintthan"fast"(1lessproperty),shouldn'tit?

functionSlowPurchase(units,price){this.units=units;this.price=price;this.total=0;this.x=1;}varslow=newSlowPurchase(3,25);//xpropertyisuseless//soIdeleteitdeleteslow.x;

"fast"objectsarefaster

functionFastPurchase(units,price){this.units=units;this.price=price;this.total=0;this.x=1;}varfast=newFastPurchase(3,25);

Page 25: Finding and debugging memory leaks in JavaScript with Chrome DevTools

REALITY:"SLOW"isusing15timesmorememory

Page 26: Finding and debugging memory leaks in JavaScript with Chrome DevTools

TimersTimersareaverycommonsource

ofmemoryleaks.Lookatthefollowingcode:

Ifwerun:Withthiswehaveamemoryleak:

varbuggyObject={callAgain:function(){varref=this;varval=setTimeout(function(){console.log('Calledagain:'+newDate().toTimeString());ref.callAgain();},1000);}};

buggyObject.callAgain();buggyObject=null;

Page 27: Finding and debugging memory leaks in JavaScript with Chrome DevTools

ClosuresClosurescanbeanothersourceofmemoryleaks.Understandwhat

referencesareretainedintheclosure.

Andremember:evalisevil

vara=function(){varlargeStr=newArray(1000000).join('x');returnfunction(){returnlargeStr;};}();

vara=function(){varsmallStr='x',largeStr=newArray(1000000).join('x');returnfunction(n){returnsmallStr;};}();

vara=function(){varsmallStr='x',largeStr=newArray(1000000).join('x');returnfunction(n){eval('');//maintainsreferencetolargeStrreturnsmallStr;};}();

Page 28: Finding and debugging memory leaks in JavaScript with Chrome DevTools

DOMleaksarebiggerthanyouthinkWhenisthe#treeGC?

#leafmaintainsareferencetoit'sparent(parentNode),andrecursivelyupto#tree,soonlywhenleafRefisnullifiedistheWHOLEtreeunder#treecandidatetobeGC

varselect=document.querySelector;vartreeRef=select("#tree");varleafRef=select("#leaf");varbody=select("body");body.removeChild(treeRef);//#treecan'tbeGCyetduetotreeReftreeRef=null;//#treecan'tbeGCyet,dueto//indirectreferencefromleafRefleafRef=null;//NOWcanbe#treeGC

Page 29: Finding and debugging memory leaks in JavaScript with Chrome DevTools

E

Rulesofthumb

Useappropiatescope

Unbindeventlisteners

Managelocalcache

Betterthande-referencing,uselocalscopes.

Unbindeventsthatarenolongerneeded,speciallyiftherelatedDOMobjectsaregoingtoberemoved.

Becarefulwithstoringlargechunksofdatathatyouarenotgoingtouse.

Page 30: Finding and debugging memory leaks in JavaScript with Chrome DevTools

ObjectPoolsYounggenerationGCtakesabout10ms.

Maybeitistoomuchtimeforyou:

Insteadofallocatinganddeallocatingobjects,reusethemwithobjectpools.

Note:objectpoolshavetheirowndrawbacks(forexample,cleaningusedobjects)

Page 31: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Threekeyquestions1. Areyouusingtoomuchmemory?

2. Doyouhavememoryleaks?

3. IsyourappGCingtoooften?

Page 32: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Knowingyourarsenal

Page 33: Finding and debugging memory leaks in JavaScript with Chrome DevTools

BrowserInfoYoucanmeasurehowyourusersareusing

memory.

Youcanmonitortheiractivitytodetect

unexpecteduseofmemory

(onlyinChrome)

>performance.memoryMemoryInfo{jsHeapSizeLimit:793000000,usedJSHeapSize:27600000,totalJSHeapSize:42100000}

Page 34: Finding and debugging memory leaks in JavaScript with Chrome DevTools

jsHeapSizeLimit

usedJSHeapSize

totalJSHeapSize

theamountofmemorythatJavaScriptheapislimitedto

theamountofmemorythatJavaScripthasallocated(includingfreespace)

theamountofmemorycurrentlybeingused

Page 35: Finding and debugging memory leaks in JavaScript with Chrome DevTools

IfusedJSHeapSizegrowsclosetojsHeapSizeLimitthereisariskof:

Page 36: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Imean...

Page 37: Finding and debugging memory leaks in JavaScript with Chrome DevTools

ChromeDevToolsCtrl+Shift+I

⌥⌘Ihttps://developers.google.com/chrome-developer-tools/

Page 38: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Memorytimeline

Page 39: Finding and debugging memory leaks in JavaScript with Chrome DevTools

MemoryProfilingTakingsnapshots

Page 40: Finding and debugging memory leaks in JavaScript with Chrome DevTools

ReadingyourresultsSummary

Page 41: Finding and debugging memory leaks in JavaScript with Chrome DevTools

EYE-CATCHINGTHINGSINTHESUMMARY

Distance:distancefromtheGCroot.

Ifalmostalltheobjectsofthesametypeareatthesamedistance,

andafewareatabiggerdistance,that'ssomethingworthinvestigating.

Areyouleakingthelatterones?

Page 42: Finding and debugging memory leaks in JavaScript with Chrome DevTools

MOREEYE-CATCHINGTHINGSINTHESUMMARY

Retainingmemory:thememoryusedbytheobjects

ANDtheobjectstheyarereferencing.Useittoknowwhereareyouusingmostofthememory.

Page 43: Finding and debugging memory leaks in JavaScript with Chrome DevTools

ATIPABOUTCLOSURESIthelpsalottonamethefunctions,soyoueasilydistinguishbetween

closuresinthesnapshot.functioncreateLargeClosure(){varlargeStr=newArray(1000000).join('x');varlC=function(){//thisISNOTanamedfunctionreturnlargeStr;};returnlC;}

functioncreateLargeClosure(){varlargeStr=newArray(1000000).join('x');varlC=functionlC(){//thisISanamedfunctionreturnlargeStr;};returnlC;}

Page 44: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Switchingbetweensnapshotsviews

Summary:groupsbyconstructornameComparison:comparestwosnapshots

Containment:bird'seyeviewoftheobjectstructureDominators:usefultofindaccumulationpoints

Page 45: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Understandingnodecolors

Yellow:objecthasaJavaScriptreferenceonit

Red:detachednode.Referencedfromonewithyellowbackground

Page 46: Finding and debugging memory leaks in JavaScript with Chrome DevTools

YoucanforceGCfromChromeDevTools

WhentakingaHeapSnapshot,itisautomaticallyforced.InTimeline,itcanbeveryconvenienttoforceaGC.

Page 47: Finding and debugging memory leaks in JavaScript with Chrome DevTools

MemoryleakpatternSomenodesarenotbeingcollected:

Page 48: Finding and debugging memory leaks in JavaScript with Chrome DevTools

The3snapshottechnique

Page 49: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Rationale

Yourlongrunningapplicationisinanstationarystate.

Memoryoscillatesaroundaconstantvalue.

(orhasaconstant,controlled,expectedandjustifiedgrowth).

Page 50: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Whatdoweexpect?

Newobjectstobeconstantlyandconsistentlycollected.

Page 51: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Let'ssaywestartfromasteadystate:

Checkpoint#1

WedosomestuffCheckpoint#2

WerepeatthesamestuffCheckpoint#3

Page 52: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Again,whatshouldweexpect?

AllnewmemoryusedbetweenCheckpoint#1andCheckpoint#2

hasbeencollected.

NewmemoryusedbetweenCheckpoint#2andCheckpoint#3maystillbeinuseinCheckpoint

#3

Page 53: Finding and debugging memory leaks in JavaScript with Chrome DevTools

ThestepsOpenDevToolsTakeaheapsnapshot#1PerformsuspiciousactionsTakeaheapsnapshot#2PerformsameactionsagainTakeathirdheapsnapshot#3Selectthissnapshot,andselect"ObjectsallocatedbetweenSnapshots1and2"

Page 54: Finding and debugging memory leaks in JavaScript with Chrome DevTools
Page 55: Finding and debugging memory leaks in JavaScript with Chrome DevTools

The3snapshottechniqueevolved

Page 56: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Simpler&morepowerfulbut...Doyou

haveChromeCanaryinstalled?

Page 57: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Brandnewfeature:

RecordHeapAllocations

Page 58: Finding and debugging memory leaks in JavaScript with Chrome DevTools
Page 59: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Bluebars:memoryallocations.Tallerequalsmorememory.Greybars:deallocated

Page 60: Finding and debugging memory leaks in JavaScript with Chrome DevTools

Let'splay!Youcangetthecodefrom:

https://github.com/gonzaloruizdevilla/debuggingmemory.git

Oryoucanuse:

http://goo.gl/4SK53

Page 61: Finding and debugging memory leaks in JavaScript with Chrome DevTools

[email protected]

@gruizdevilla

(btw,wearehiring!)