Transcript
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!)