The Art of Debugging by Remy Sharp
[APPLAUSE] OK, everyone can hear me.
So I appreciate it is the end of the day.
There is just two more talks to get through.
I haven't prepared a talk-- I haven't prepared a talk with lots of code in it, not too much to code.
So I won't [INAUDIBLE] any brains.
And I've got several caveats throughout this talk because I am English, I have to caveat anything I do.
This is my debugging workflow.
This is what works for me.
These are some of the things that are specific to my workflow.
And hopefully you'll find some things useful.
And there will be some bits that you can copy and paste with your eyeballs later on.
But before I get into-- well, not before-- but-- sorry, right.
So, The Are of Debugging.
So now we've got 50 minutes of Q&A. Yeah?
No? OK, well maybe not.
Assuming you're not a robot and you do write software, writing a bug or two is fine.
Actually, the truth is it's almost the opposite.
It's the opposite of don't write bugs.
Debugging is about writing lots of bugs.
Writing lots of software, the artifacts of writing software, is bugs.
And having bugs, I like to think that people fix their own bugs and other people's bugs, this is what gives you experience.
And for me, I really enjoy bug fixing and diving into bugs and debugging, because it's variety.
And it's what I have a lot of experience in now, because I keep on writing bugs.
But yeah, I like solving problems like this.
There's no hard and fast skills that you can acquire.
There's no silver bullet to debugging.
There are some tools, but you have to pick and choose the right tool for what you're actually trying to solve.
So the company I used to work at 10 years ago, we used to have-- when we took on new employees, what we would do is we would get them really excited about what we were working on, the technical challenges.
And they would join on their first day.
And we'd sit them down.
And they'd be like, OK, what am I going to be working on.
It wasn't that exciting, really, it was kind of financial software.
But they were excited about what they were going to be working on.
We sat them down and we told them, you are going to be bug fixing for three months.
And it kind of let the air out of their oxygen tank.
And they're kind of disappointed.
They walked off and went away.
But what happens is they got to work on loads and loads of little different projects for the next three months.
They would jump in, a couple of days, fix a bug, move on.
Whereas I might be working on a feature that takes six, nine, 12 months.
And I get to release one thing.
I'd be working on the same thing the whole time, and even then someone might come in and bug fix and get part of the glory because like cocked it up when I actually released it in the first place.
And when those new joiners finishing and their time was up to do bug fixing, we were rotating someone else on, they're pretty keen to stay on because it gave them all that variety.
And like I said, it's this experience.
The designer I use to work at, at this previous company, he was a visual designer, but he also did CSS and HTML.
And I was back end and front end.
But my CSS wasn't as good as his, certainly.
He was the expert.
In fact, I think he was the only person writing CSS.
And I would have a go at fixing, like trying to make a layout.
And it would be broken, because we're talking IE6 days.
And he would just look at it, maybe kind of look at a couple of stars, but just look at it and say, oh yeah, you need zoom one.
That kind of classic IE bug fix.
And what he's done is basically he didn't skip the debugging processes.
He's seen that bug in all its permutations, and is able to just recognize that there's a high chance of the bug being fixed just with zoom one.
I can look at problems pretty quickly and get a fast idea of what the actual issue is.
But it does, it just boils down to just doing bug fixing after bug fixing, over and over again.
And you can do that kind of eyeballing a bug and fix it like that.
So before I really continue, I have two disclaimers.
So before anyone gets too preachy, this is not my guide to debug everything.
There are many, many ways.
If some other way, then that's cool.
But I don't have any projects that require frameworks.
I worked for one company that worked in Angular and managed to circumvent that madness.
But I haven't used reaps, I haven't used Amber.
I used jQuery, but I haven't got any requirements for these libraries at the moment.
So the tools I use don't factor for those libraries.
OK, so if you purity right react code, some of this still should apply because it's about the ideas of debugging, but I don't have talks for these kinds of things.
And the thing is, the more complicated the program you're trying to write, the more complicate the software becomes, the more complicated the tools have to become.
And we've gotten to the point where-- like React has rebuilt the entire, almost the language from the ground up again.
But now apparently it's the cool, hotness, hipster thing.
But you build real things, like Instagram, I think, is react.
But they've got their own debugging tools.
They've literally had to build their own debugging tools so you can get inside and look at state of the application and life cycles and all that kind of stuff.
And same with Amber.
They have their own debugging tools.
The good thing about Chrome Dev Tools is it has an extension API, they are extending the actual library itself.
So yeah, because when I debug, I am debugging the actual source that I deliver to the browser.
I will talk about source maps a little bit, but the bottom line is things that React are going through a processing step.
And the code that it generates is not particularly for humans, it's for the browser.
So you don't want to be debugging that code.
You are going to have to be going via source maps.
And when you hit source maps, you don't have the full suite of tools that are available to you.
You can still debug, but not 100%.
And that's part of the reason why I don't do it yet.
Yeah, so this is my other disclaimer.
So I might get lynched later because of this, but the work I do at the moment doesn't require me to do a great deal of cross browser testing.
And by great deal, I mean very little.
Now, if I actually have to build a website, it will get tested in the full range of IE, Firefox, and Chrome.
It's just functional code.
If an expression is broken, if there's a bug in the actual expression somewhere in the code, in the functional code, there's a bug in the code.
It doesn't matter what browser.
And it will break.
And if I fix it, if they've implemented ES5, then it will work.
Now fair enough, if I'm deploying to IE8, then things like a RAID or index of might not work.
Couple bits here and there are missing.
I just need to make sure the code runs.
So because of that, I haven't looked at any detail, or even in the last 12 months, what IE's developer tools look like, just because I've not needed to.
I know Chrome dev tools very, very well.
I spent a month working with Firefox developer tools, which are pretty good.
There's some nice unique tools inside of there.
I am not a fan of Safari's developer tools.
And I'm not a fan of Safari in general, so I don't like to go into that.
I do try and spin up my own headless browsers to do testing.
And I do use those.
But that's a whole different kettle of fish, and very difficult. But
it's due to the nature of my current work.
So, They Are of Debugging.
And it is an art because Wikipedia says it's something of an art.
So it's an art.
So this is my art of debugging.
The first is three parts.
You might have seen me kind of mention this in the past, but it's my three parts to debugging.
This is the hardest part the job in my opinion.
This is the most important part of the job, and the hardest part of the job.
More often than not, I'll get a bug report that is saving, doesn't work.
I can't replicate that bug because it doesn't actually say anything.
So firstly, you need to be diplomatic in your response.
Not like, yes it does.
Goodbye, as much as I'd like to.
You need to glean as much information as possible.
Now if the site their talking about is JSB and I know that saving works, but it means that they've encountered a situation where it's not working for them.
And going back and saying it works for me is a cardinal sin.
You'll be sent to work with IE6.
Saving does work.
It doesn't work for them.
There's something that's happening that's in between that experience.
So I get the URL back from them.
And the first thing I do is a litmus test.
Like don't jump straight to kind of replicating their entire environment, do that litmus test to see if there is a bug there.
Most time there isn't, but you might have the lucky one where you can just fix it there and then.
So there are a series of events that ten what's more likely is a series of events have occurred to create this situation.
So carefully, meticulously, and systematically I will get to the point where I can reproduce this bug.
And systematically it's important because really debugging is the end of the process.
You should've caught it in the tests.
So if I can replicate systematically, I'll grab that and make it a test.
And then I can code against that test.
So I can actually just put that into its own test and just fix the code against the test rather than trying to fire up the browser and recreate that whole interaction and so on.
Some key tools to replicating cleanly.
The privacy mode in a browser, or incognito in Chrome.
This gets me a clean view, without any-- generally-- without any history, and without any plug-ins.
Some of my plug-ins are enabled in incognito, like one possible for instance.
And that interacts with the page.
It affects the global scope.
But I've had at least one every six months, one bug every six months, where I'll fire up an incognito window and the bug is not occurring the way that they described.
I asked for a screen shot of their browser, not just what they're looking at, but their entire browser.
And I can see a line of icons.
So I asked them to do the same thing, incognito.
And I find that actually the bug doesn't occur.
So what we're doing is getting a clean view.
Remember, if you have multiple incognito windows open, the history is still going to carry across.
And the other thing is multiple profile.
So you can have-- I have my own personal profile, which is logged into Gmail and so on.
I've got an anonymous user, which has no history, and basically starts from scratch.
So every time I go in there's no cache there.
There's no context.
There's no plug-ins at all.
No one password or anything.
And the other one I've got is like a troll user that has security set to the absolute max, cookies disabled, because you get situations where users have this stuff disabled.
And it just breaks when they go into the site.
So you want to be able to jump into that mode without having to mess up your own profile, basically.
And then once I'm able to replicate consistently, the next job is to pair it down so that I can isolate it right down to it's kind of unit form, I guess.
And this is what JS Bin was for, to take a bug, get it down to its very smallest form, send it off to someone who can actually fix it.
They make the changes, send it back to me.
And this is what I was talking about with extensions.
You want to get all the extensions out of the way in your browser so they're not having a play on the actual page.
And yeah, you just want to pair down to the very smallest form, if you can.
And again, if you've got a project just-- the project I'm working on at the moment, there's a lot of code that the user will interact with on the command line.
I need to strip out the block that's causing the bug so that I can test it as a separate unit, basically.
Once I'm able to replicate and isolate, the bug fixing is a piece of cake.
Everything is there.
All I have to do is tweak some value.
I already know that the data going in is wrong, or the data coming out is wrong, or there's an exception because the situation occurs.
So I know why it's breaking, because I have all the information around it.
The actual bug fix is relatively easy.
So assuming that you can type at a relative speed.
But yeah, this is my art of debugging.
The thing is, what if you can't replicate? You're shit out of luck.
You can blind code the solution, but you're never going to know if it's actually solved.
You're still going to have the potential of it being broken.
And you could have something-- you could have a Heisenberg bug on your hands, which is a cool thing to say.
So you can go back to your project manager and be like, this is a Heisenberg bug.
The Heisenberg bug is a bug that changes shape as you debug it.
It changes form.
It's pretty cool, super annoying.
So I've had this kind of thing.
It's not exactly, but it's kind of like this.
Basically, I fixed the bug.
I've got my tests.
We're working locally.
Push it to Travis continuous integration, and it fails.
The Travis environment is different to the on that I'm running in, so it causes some other bug to occur.
So I'm now trying to replicate the Travis environment to fix the bug that Travis sees because some other user may have that bug.
And another and more importantly, years ago when I was using Firebug, Firebug is intrusive to the browser, to the dom.
It would actually introduce and change the dom, introduce variables to the dom and change the dom.
So that can have an effect on debugging.
And the recommendations for-- if you're doing profiling, like rendering profiling-- the more things you turn on, the more things you want to record, the more tabs you have open, they have an effect on what you're looking at.
They are contributing to the performance, or the lack of performance on the page.
So it's worth thinking about cleaning the environment as much as possible.
So for me, this might be because I've just been doing the same thing over and over again, but debugging all comes down to state for me.
I was thinking about this long and hard because it felt really quite simple.
Either state is the lowest common denominator and there is nothing else.
Or I literally can't see the wood for the trees.
But to me, it's all about state.
Departing is be able to get into the application and seeing its state, being able to change its state, and being able to maintain the stack in which we got into that state.
And I saw some react or flex or flux or whatever it's called, some wanted built a debugging tool for the Facebook library.
And it was all about looking at states.
And it's the same wherever we go.
We're looking at state.
Whether you're debugging with an alert box, consoles, canvas rendering history, we're looking for states.
And I see it as being these two types of states.
So the first one is passive state, where I am able to look at something that's happened.
I can look but not touch, basically.
I can look at the network requests that were made, or literally how the canvas had been drawn, like frame by frame.
Or I can look back at all the web socket data that's come up the wire.
So yeah, we've got rendering histories, memory usage, and so on.
There's lots of things that give us actually the insight to state.
And we have interactive state, where we can actually go ahead and make changes to the state.
And this is where it gets interesting, because you can go into the browser and make the bug fix.
And this is where I do most of my debugging.
I can look at the state of the application, but normally there's something that's wrong.
I want to change the state.
And I need to do that without losing the context in the stack.
So dev tools is the-- I'm going to show you some live coding examples-- live examples of debugging, but that dev tools is the one that I use, because I can not only change the state of the application-- and you can do that with all the other browsers well-- but I can commit that to disk and never be leaving the inspection state.
I can commit it to disk and I'm not having to memorize the change that I made and jump back and forth.
And it's very powerful stuff for me, basically.
So yeah, the stack's important.
And as soon as you try and save a change to a function in memory or to disk, dev tools is the only one that's going to maintain that stack, the context-- the path in which you got to that point of state.
Anything else is going to-- you have to reload your entire stack to be able to get back to that point, because you transpiled the code from using ES6 imports, you have to re-compile that code, get a new source map, so that the browser can put the code back together again.
And this is the main reason why I haven't jumped ship to ESNext yet, personally.
So, there are two ways of debugging.
I've kind of categorized them into two methods, inside out and outside in.
Not very clever names, I appreciate.
But outside in is where you know where the bug is, or you've got an idea where the bug is.
You can put like a debugger statement to break the code.
And pause it and actually go in and look at the state.
You can do break points.
You can do conditional breakpoints where an expression becomes true and the code will break.
And you can actually go in and look and step through or step backwards.
But outside in, we are seeing more tools that help us take this approach, where you're looking at the page but something is changing, but you're not sure what's causing that change.
So you want to break on dom subtree modification.
Like you know that an element is being inserted.
You're not sure is inserting, like where the source is.
Or some XHR request is being made, but you don't know where that comes from or where it's going back to.
So we have dom break points, Ajax breakpoints, replaying XHR so we can repeat the XHR code over and over again to get back into that point of code.
We can do timeline screen shots as well.
So let me show you-- there's just really big text on my screen that says live demo mofo.
So these are my favorites, and this is where I lose my clock as well.
So this is time for live demos.
So I hadn't actually tested trying to switch my screen, so this will be-- cool, you can see.
OK, you can see my screen.
So I've got-- just going to make it so it's nicely sized.
I've got Dev Tools open.
I've got a little demo project.
A chap called Glen Madden wrote a program, like a get repo, that demonstrates ES6.
So I pitched it and broken it.
Anyway, I'm going to use it for this demo.
So I've opened up Dev Tools, got a fairly clean view of Dev Tools at the moment.
And the first thing I want to do is create a work space.
So what this program does is I run it, and it shows me animated GIFs because the world is based on GIFs.
Why aren't we getting three-- screw it, it doesn't matter.
So animated GIFs.
OK, everyone loves animated GIFs.
And I click Run on it and it randomises the order.
That was me.
And I've got the source code here.
You can see the origin.
Local host [INAUDIBLE] 8,000.
You can see the scripts, we're used to looking at this kind of stuff.
Font size, OK.
It's not great, is it.
OK, so what I'm going to do is just drag in the directory.
This is the directory here.
I'm just going to drag it into the sources panel.
So Chrome is asking me if it can have access to write to that directory.
I'm going to say yes, go ahead.
But the code that I'm looking at that runs this page doesn't know that I want it to save it to disk.
So I have this extra direction my sources, so I can see lib main.
But I need to link this file, main.js,
to this file down here.
I'm just going to right click map to local file system.
And I always have a star shoot sitting in the roof of that directory as well.
But I'm only going to map one file.
Chrome does its best job to match it to the one if-- like the file name it finds.
So if I had a version [INAUDIBLE] on the end, I just get rid of that and find the file.
It has to reload.
But now it knows that this origin maps directly to this entire directory.
But it's also mapped the CSS as well.
And I'll show you the CSS in a moment.
So let's close all.
Let's just go to main.
OK, so now that I've done that, any changes I make to this, like I could just do console.log,
I saved it.
I just do command s.
See that? And if I hit refresh, I get a syntax error.
I've hit refresh, I get-- it's reloaded off disk.
So not magic.
What's interesting here is I can actually change this live in memory.
So I can't set a break point inside of these callbacks because they're just one line.
I want to change it so that I can dot then res dot slice 02.
So I just want 2.
So I just get 2 every time.
I haven't reloaded the page at this point.
I had a bug in the code.
It was showing to me animated GIFs, which you may not have too many animated GIFs.
I was able to just make a change in memory.
It affected this function that was loaded memory.
And it saves.
So 2 is the wrong number.
So I'm going to set a breakpoint.
Still can't set a break point.
I'm going to set it so I can set a break point.
I haven't written much ES6.
And my fat arrow knowledge is not very good.
I'm just going to his save.
And now I can set a break point.
And it doesn't break.
And if that happens, you just close your eyes, OK.
It paused, exactly in that point.
That's why you don't do live demos. ' So change that to 4.
And this is really important.
When I hit Save, when the code's paused on this line, what Chrome is allowing me to do is back the pointer up, like the point of execution is backing up a little bit.
So it hasn't actually run this line of code, the slice.
And I've made a change.
So I can change it to 10, hit Save.
And the point of execution is literally just backing up outside of the function and going back in again.
If I hit play, it'll give me 10 GIFs.
So that's how I debug.
I literally do a workspace.
Map the two things together.
And I find the code.
I have a break point.
And I just pause it there and then.
Don't get too worried about Fat Arrow, if anyone is, I always do.
The other thing, though, is the Elements panel down here, the CSS is mapped.
So these images are-- they are 33 VWs.
So maybe I actually want 50 VW.
So I make the change.
And come on.
Should we just make the width a little bit less.
There we go.
So 49, that's a nice, arbitrary number.
Seems like it should fit.
And I'm happy with that.
Previously, I would have taken that-- you use a brain screen shot and put into my code.
But because I've got the workspaces in place, this has actually modified the source CSS file.
If I want to change the color of the red, I can use the picker that's here, and go ahead and use old happy face here.
And that's done.
It's saved to disk.
Save to disk.
Some people put it like, that seems a bit fast and loose for me.
First of all, source control, you should have this.
This is hopefully not new to you.
But also, the next thing I want to show you is basically undo.
So let's change that-- no, let's not change that.
Let's change the white.
And let's put the button over here.
Or let's just delete the bottom, screw it, let's get rid of the button.
I think it should be 3.
I can undo all of this.
So I can go back to the elements and controls z and put the button back.
And it will put it back in the same place.
And let's go to the-- it's still white.
I'm just doing control z again.
And the color's gone back.
It's undoing way back through the panel that I'm focused on.
So whilst I haven't reloaded dev tools, it has a full undo history with each panel.
So it's not destructive.
But in Sublime, if you took Sublime, made a whole bunch of CSS changes and then closed Sublime and opened it, you wouldn't be asking, why can't I undo.
When you reload dev tools you destroy your history, but you can undo.
OK, so I actually really like tweaking the CSS from this corner.
I think it's pretty powerful.
OK, so the next-- these are my favorite things.
So the console.
I know I am I'm using pretty basic demo.
Let's get rid of Remy because that's really distracting me.
Go away, seriously.
Since page doesn't use jQuery, and I'm pretty familiar with the dollar function, we have it.
We can dollar script, and it's a shortcut to a document dot query selector.
And I have dollar dollar script, which is a document dot query slash [INAUDIBLE].
And I like that I can open dev tools and I can just write this code and it works.
Now I've got a pole background, which means that when I see dollar underscore I've got an understanding of what it does.
It's really big.
Can you see the underscore? It's pretty small, but yeah? Cool, thumbs up at the back.
Dollar underscore is the result of the last expression.
So whatever the result of the last expression is, dollar underscore contains it.
So if I do dollar underscore dot length, I'm going to get 4, because the previous result was a DOM nodelist that had length of 4.
If I do dollar underscore now, I'm going to get the number 4.
This is really cool for doing things like this, where I can grab the h1.
Literally all I've done is focused on it.
When I make my font really big it makes it difficult.
Focusing on it, and if I did dollar 0, I get the element I've selected.
If I do dollar one, I get the previous one I selected.
But I want dollar 0.
So dollar 0 is the current element that I've selected in the Elements panel.
And then I can dollar underscore dot parent element, or parent node, dot remove child dollar underscore.
Dollar underscore is pretty cool.
And dollar 0 is pretty cool as well.
So the last one-- last thing in console that I'm a big fan of is copy.
So the console API has a copy function.
And it copies all kinds of things.
So we can dollar scripts, there.
I'm going to map-- sorry-- I'm going to map scripts through function.
Return l dot-- so I just want to get sources out.
So source-- looks about right.
So this gives me an array of the script sources.
If I just run that again-- if I do copy dollar underscore, I get an adjacent array, basically.
I get the same thing with [INAUDIBLE] projects.
So a 12, b, Remy, so on.
I get adjacent objects.
I can do the same thing with the dom.
So I can do copy dollar 0.
And I've got the outer HTML of the element that I was selected.
So look, let's just click on the h1.
Let's go back.
So dollar 0 is the h1.
So I'm going to do copy, dollar 0.
And if I pace that out, I've got the HTML of the h1, which is pretty cool.
I like copy a lot.
OK, so the next thing I want to show you is timeline screenshots.
So I've taken a timeline-- so I've used the-- oh crikey, this is big now, isn't it.
So I recorded this early on just that I didn't have to do too much hands on stuff at this point.
But basically, Chrome allows me to take screen shots during the time line.
So I checked this box.
Or I can do it from the network, and there's like a camera that you click.
I've used this to debug taking an outside in approach.
Basically I can see that the page is relaying out, but I'm not sure why it's happening.
So if I hover over these screen shots, I don't think you'll be able to see it very well, but just between this point here, the whole page relays out.
And I couldn't work out-- I didn't know what was causing that.
So I use these screenshots to kind of create a marker to say, OK, I know at this point it's good, so let's have a look at everything that happened before that point and try and determine what was in the way of that completing its layout.
So it's something before it that's taking too long.
And there it was.
It was this big blob of code mirror.
And by using the screen shots, I could work out just visually jump straight to what could be the possible source.
Let's put my tabbing code ahead of code mirror.
And now the fixed version is like my tabs lay out straight away, and code mirror is kind of tucked away and hidden.
But it meant that I could use the screen shots for kind of an outside in approach to debugging.
So back to our ponies.
Another outside in approach that I mentioned earlier is a break on the basic dom break point.
Say I start the page up.
I'm not familiar with the actual code.
I can find out what's modifying-- when I run, I can see that there are elements in this dom node.
They're being inserted into this dom node.
So what I can do is right click and do break on subtree modification.
I know that's super tiny, but there is a small menu.
I can't increase font in menu.
And now that will appear in my dom break point.
So when I click Run, something is going to change at dom and put new dom nodes into the div GIFs.
The code is paused.
If we take a look, if I hover over the lm element, I can see div hash GIFs.
And I can see it's doing the URLs map using ES6 templates.
And that's how it works.
So I've used that outside approach to just say break when something changes this piece of code, this part of the page.
And show me what codes are causing that.
And if this was inside of like a jQuery library or some kind of library, I can actually black box that library.
And I should be able to back out a little bit.
And at same time here, actually I can back out through code.
So I can see from the call stack, no I can't.
Maybe I need Async.
But there's another trick here using the Async check box.
It costs a lot of memory when you're actually debugging.
It kind of maintains a full call stack of all the Async calls that take you to that point.
But it's quite useful if you got like a set timeout that's calling some call back, or an exit [INAUDIBLE].
Remember to turn it off, though, because Chrome just gets quite unhealthy if you don't just turn it off afterwards.
OK, so I've got time for one last demo.
OK, so this one was a bit harder.
This is memory debugging.
And I've gotten to the point where I can debug memory fairly confidently in Chrome.
And I feel like memory leaks is a hard thing to solve.
And it's been historically hard, because I think the examples on the internet are all like, let's create a memory leak.
Now let's debug it.
Oh, we found a memory leak.
Yeah, that's not how I ever create a memory leak.
I never go out of my way to make it.
It's always just happens to be there.
But there's two things that I'll do.
And I don't jump straight to memory leak debugging.
If I feel like something feels slow or is taking up a lot of memory or I feel like is a bit odd that it's taking up a lot of memory, I'll do these two things.
The first one is like a surface test to see if the memory usage is going up and up and up.
And if anyone remembers the old days of IE6 kind of thing, you look at the Control Alt Delete and just watch memory increase.
Chrome has the same thing.
I'm pretty sure the other browsers have the same thing as well.
You can see the memory footprint.
But what you want to do is force a garbage collection every-- like during the process that you're repeating, which you start off with your baseline.
You create your action that you think is leaking.
Force a garbage collection.
Repeat that action.
And then stop your recording.
And if you memory usage hasn't gone right back down to where it was when it started, you've got a leak, basically.
And this is just to get an idea if there's a leak.
But from that, the next two tools you can look at are live recordings of heap allocations and heap snapshots.
So I'll show you that.
I'm going to start recording.
And I'm going to play this amazing game that I wrote.
Just excuse me while I win all the money.
OK, not so good.
So I'm going to start a new game.
Do some more of this.
These blue bars, these are objects.
So the grey bits at the top are objects that it was able to deallocate.
These blue bars are ones that it can't get rid of, are just kind of still knocking around in memory.
This is another clue that there is something wrong.
Like these should've gone away.
But what I tend to do here is actually take a two to snapshot comparison approach.
So I'm going to start again.
And with this, with memory leaks, I do encourage like trying to get to reset state.
Always go back to the baseline.
I'm going to take a heap snapshot from the very beginning of the program.
I'm going to run a task which I think is leaking, like the new game.
I'm just doing it three times just trying to emphasize the problem.
I'm going take another snapshot.
And from there, I'm going to compare to the previous snapshot.
So I'm basically looking at deltas.
I just want to look at the differences.
So this is what I'm looking at here.
Now I can't remember where, I saw video that talked about there's basically everything in brackets I should ignore.
And there are some people from Chrome here and they can tell me if that's true or not, but basically I'm going to ignore everything in brackets.
And I'm going to be looking down the page and looking for where this column is increasing, the deltas.
So where there's more left over.
And I can see-- so I got bracket, bracket, bracket, object, array-- that's a very useful system.
That sounds like something I'd want to know about.
I got two here, HTML div element and detached dom.
If I open this up, that red-- so we've got two colors here, yellow and red.
That is a leaking object.
And that's causing a memory leak.
And the thing is with memory leak, memory leaks, it is a case of being a private investigator.
You're going to be Magnum PI.
You're very rarely given the answer.
You're given a bunch of clues.
That's the best I can hope out of this memory debugging.
But the clues are down here.
So I can see there was something to do with a click.
And I can see that there is this dollar in XUY.
So I was using the XUY library, which is similar to jQuery, but not jQuery.
And I could see this object here, cache.
And if I think-- if I think about how this works, it means that something is being cached.
It's to do with a click handler.
And it's not being cleaned up properly.
And there's a pointer back to that dom node.
So I've got something that is still pointing to a click handler that should have been destroyed.
And then I would go into the code and actually look at where the source of the problem is.
But at least this confirms, 100%, there is a memory leak, because that red node.
I'm still OK for time.
So I'll do one last useful my favorite tools.
So the last one I really like is throttling.
So you can do network throttling.
Ironically, I actually filed a feature request earlier today to Chrome so that you can do network throttling on one single origin, so everything goes fast but one origin is slow.
And I could load up the page and I make the change.
And then the internet went to offline.
And when I submit it, it vanished.
And so maybe I had the throttling turned on in offline, but it didn't work.
So they haven't got the feature request.
But I can emulate offline for things like service workers.
I can emulate service workers by pretending to be offline and not having to shut down my server.
I can emulate a slow connection, which is really useful for getting an idea of my fonts making the whole page blank.
And I use this on JSB so you kind of get an idea of what it feels like load over, maybe, across the world, because I know whether our CDN-- well, actually we use a CDN for most of the code now, but if it takes too long to get the main program over the wire, what does it feel like? And using the throttle connection and the screen shots, I was able to see that I had a prob with the fonts being loaded way too late.
And there was like this double flash, not just a flash of no content-- it was just this text.
And then it flashed, and flashed again when the fonts came down.
So I was able to rearrange my code loading and put the fonts much earlier on.
You do have to remember to turn it off.
I did a workshop on Wednesday.
And I left it on GPRS and I was wondering why everything was slow.
And it was because I'd left it on.
I'm not 100% sure if this affects other windows or not.
And I don't know if affects XHR uploads.
I've got [INAUDIBLE] as an open bug for that.
But it's still pretty useful.
Actually testing a slow connection, it was impossible.
You'd have to wander around outside until you get a slow mobile connection.
So those are some of my favorite tools.
The bottom line is, there is no silver bullet.
There are lots of tools out there.
You need to-- I wouldn't say you need to know them, but it's useful to get an understanding of what your browser can do or what your tools can do.
And there are a whole bunch of tools that go way beyond the browser, like Get Bisect, super useful for debugging, and some other stuff.
So there are no more slides.
I am At the end.
Thank you for listening.
And I'll invite Bruce to join me.
[APPLAUSE] Thanks, Rem, come with me to the comfy chair of interrogation.
Yours is that one so they can see you.
Of course they've probably seen too much of me in the last two days.
Or last couple of years.
Sorry, that's an English display of affection, a courtship ritual.
Couple of questions because there's not that much time.
Somebody called Dion Van Rijswijk Said can source mapping in Chrome Dev Tools be done for Sass? Yes.
How? You need to enable Source Maps in your watch, your build.
And in the settings of dev tools-- and I think Firefox has this as well-- you just check-- well, I think CSS Source Maps is enabled by default, but the extra bonus you can get is checking the live reload.
So by checking the live reload, what dev tools will do is watch the disk as well.
And if it sees that the source-- the output CSS from your Sass or Less or stylus or whatever you use, has changed, it will inject that back into the browser without any additional tools.
The one huge gotcha is if you change any of those CSS properties from the elements panel, as soon as you make that change, it'll write it to the CSS file and not the Sass file, the source file.
Because you might have a mix in that produces one color that comes from six different places.
And Chrome-- like Dev Tools can't work out where those have come from.
You can't get that from a source map.
And it doesn't give you any alert.
It just changes it.
And it'll write it to the disk.
So when you hit Refresh, because your Sass process hasn't rebuilt the CSS files, it reads the changed file on disk.
It looks like it saved in Sass.
You carry on your merry way.
And I wasted like three hours trying to work out what on earth happened.
So if you want to, it'll show you, like, styles.sass.
Click on that link and change it in sources panel, not the elements, otherwise you will get burnt.
But you can do it and it works really nicely.
So there you are.
Remy's just saved each of you three hours, so send him some cash.
Geran Hyman's asked, any comments on debugging Async slash multithreaded slash worker type of code.
Yes, there is a little check box that says Async.
Check the check box, and you'll have all your Async goodness.
It literally will maintain the stack across asynchronous calls.
To debug-- I haven't debugged a worker in a long time.
But I know you can debug service workers, which run in a separate thread.
And you have to literally just switch context to the service worker.
And you still have the same tools.
But in terms of asynchronous, there's a checkbox basically.
Just make sure to turn it off because it does start to slow down.
The other thing that is worth adding, actually, with the stuff that's really, really new, like service workers-- I use fetch quite a bit in my code.
I like using API because they use promises.
The new technology, the debugging tools tend to come after the technology is kind of stabilized.
So debugging the service worker cache in Chrome Stable is horrible because there are bugs in it, because it's a spec that is just settling down.
They're finalizing the APIs in the browser themselves.
The debugging tools aren't finished yet.
They're still being developed.
And when you're debugging, you might want to consider switching to the nightly version of the browser to get the nightly version of the debug tools.
It's like you wouldn't stay using Textmate when you can use Sublime three, because it's new and has lots of features and lots of plugins.
So instead of using the stable dev tools, you can use the canary version of Dev Tools, which has more functionality and things have stabilized, sort of, but it's Canary.
Either way, just have both of those in your arsenal.
So two questions, there we go.
In your arsenal, I think we'll end it there.
Remy Sharp, the man who likes to say yes to questions.