Bummer! This is just a preview. You need to be signed in with a Pro account to view the entire video.
Start a free Basic trial
to watch this video
Oh The Memories! An Introduction to Browser Memory Leak Testing
56:07 with Ryan NiemeyerJust like how our brains can be overwhelmed, our web applications can also suffer from trying to remember too many things. Browser memory leaks are an often overlooked, yet important, issue in modern web development that can be overcome with the right techniques. In this session, we will take an introductory look at the tools and approaches that you can use to identify and investigate browser memory leaks. We will look at common scenarios that cause this problem, as well as patterns to use in your code to avoid leaks. Additionally, we will explore the various options for debugging and profiling leaks across different browsers and platforms. You'll leave this session with some new memories that will help you start tackling leaks in your web apps today!
-
0:00
[MUSIC]
-
0:14
I'm gonna talk a little bit about a topic that I think is, is important, but
-
0:14
not covered often and that's Browser Memory Leak testing.
-
0:23
So, Rolph already introduced me.
-
0:24
I won't spend any time here.
-
0:25
I am, I do love JavaScript.
-
0:27
I'm very happy to work with it all day,
-
0:28
every day, at appendTo with some great people.
-
0:32
And I wanna ask you a question, and feel free to type in Chat if you'd like.
-
0:36
If I were to tell you that your app has a memory leak,
-
0:38
what's the first word that comes to your mind?
-
0:40
By I, I could be your manager.
-
0:42
I could be your customer.
-
0:43
I could be your, significant other.
-
0:46
What if someone told you that, that you had a memory leak, how do you feel?
-
0:50
Well, I've had these feelings in the past, as well, and
-
0:52
I'll share a couple of the ways that I felt.
-
0:55
Denial is one, one choice.
-
0:59
Might say things like, well, maybe they just didn't wait long enough for
-
1:01
it to be recovered.
-
1:02
Maybe it's the extensions,
-
1:04
they must have some extensions installed that's holding onto things.
-
1:08
Maybe some sadness.
-
1:09
Sadness that I, that we didn't catch it.
-
1:11
Sadness that we didn't, didn't understand why it was leaking.
-
1:15
And ultimately scared, you know,
-
1:16
how do we figure this out, how do we move on how do we take care of this leak?
-
1:21
So my goal today is to discuss a little bit about the basics of
-
1:24
Browser Memory Management.
-
1:26
Talk about some real life situations that I've seen both in client projects and
-
1:30
in, in code that I, I've reviewed for others.
-
1:35
Talk about some of the tools that you can use.
-
1:36
Things that you can really zero in on what that, that memory issue is.
-
1:40
And finally, you know, the idea is that hopefully after,
-
1:43
after you leave here today you can take a look at some of your projects and
-
1:46
see if you have some of these situations going on.
-
1:50
So just for today what's our definition for a Memory Leak.
-
1:53
This isn't something I,
-
1:54
I copied from somewhere, this is just my definition for today.
-
1:59
It's temporary memory allocation that the browser's holding onto longer than
-
2:02
is necessary.
-
2:02
So you've created some variables.
-
2:04
You've created some objects.
-
2:05
And, it seems like everything is good.
-
2:09
You seem like you're done with them, you don't need them anymore.
-
2:12
But, as your application goes on you may find that it's actually causing problems.
-
2:18
As, as the longer that your browser's open.
-
2:22
So in my opinion, why is this more common today than ever?
-
2:26
Well, the rise of single-page applications, I think that, that most
-
2:29
people are pretty familiar with, with how that has come about in the last few years.
-
2:34
Some of that is due to some of the great frameworks that are out there,
-
2:37
like Angular, Knockout, and Backbone, and Ember, and, and the list goes on.
-
2:42
In single page applications, typically,
-
2:44
your browser is staying on that same page for a long time.
-
2:47
It's communicating with a back end via API calls.
-
2:51
So, by not navigating from page to page,
-
2:52
you're, you're not giving the browser a chance to really get rid of some of that,
-
2:57
that memory that may have, have been hanging around but not causing problems.
-
3:02
And part of that is, is these JavaScript heavy front-ends,
-
3:05
it's more common to be doing lots of things in JavaScript.
-
3:08
We're doing things with audio and video and canvas and
-
3:10
SVG and there's great libraries out there that help us
-
3:14
do some really incredible things in the browser these days.
-
3:18
And, and as part of doing that [COUGH] there's so
-
3:20
much code out there on GitHub and other sites, libraries, plugins, frameworks.
-
3:24
One of the big places that I've seen leaks is really in trying to
-
3:27
integrate all these things together.
-
3:29
You have a problem, you find a plugin that seems great for
-
3:32
the situation, you pull it in.
-
3:33
But the way that you're using that plugin may not be quite how the author intended.
-
3:39
Or maybe the way that you're trying to combine things together can contribute to
-
3:43
memory leaks.
-
3:46
So a little bit about how memory is, is recovered in the browser.
-
3:50
We'll talk about garbage collection, it's not just browsers.
-
3:52
There's other environments where garbage collection is,
-
3:55
is the way that memory is managed and it's very automatic so.
-
3:59
In general you don't have to do something to say to that, hey I'm done with,
-
4:02
with that memory.
-
4:04
In garbage collection when, when you don't have references to things any longer,
-
4:09
when, when nothing can reference it browser is free to,
-
4:12
to clean up that memory.
-
4:14
So you don't have to do anything specific to make that happen.
-
4:18
Now in older browsers,
-
4:19
a technique called Reference Counting was used as recent as IE6 and IE7.
-
4:24
And what, what this is,
-
4:26
is it kept track of how many times an object was referenced.
-
4:30
And when that went down to zero, then right away the browser could say,
-
4:34
I can clean that up.
-
4:36
Well there were situations where that failed, especially in circular references.
-
4:39
Just have an example there where we have an element.
-
4:42
And there's an object that points to that element.
-
4:45
And that element has an expandable property that points back to that view.
-
4:50
And this, this is a pretty naive case but
-
4:52
it, it would cause that circular reference that would cause a problem.
-
4:55
Because both of those, both that object and
-
4:58
that element would have a single reference just to each other,
-
5:02
even though nothing else might be able to reach them at that point.
-
5:07
So modern browsers implement a technique called Mark and Sweep.
-
5:12
And there's obviously a lot of complexity to how each browser
-
5:15
actually implements it.
-
5:16
But the idea is that periodically a garbage collection pass is made and
-
5:20
the mark part is that it, it, it goes from the root.
-
5:24
So that would, might be your Window object it,
-
5:26
it might be the DOM tree the various things that are considered roots.
-
5:29
It would go from there and find everything that it can reference tracking through,
-
5:34
traversing through the different trees and leaves.
-
5:37
And I would mark those objects.
-
5:39
And then I would take a sweep through all of the memory allocated and
-
5:42
I would be able to remove anything that was left over.
-
5:45
The diagram that I have here is from the Chrome Dev Tool documents and
-
5:49
I have a link to that here.
-
5:51
It describes how to use some of these tools in Chrome at least.
-
5:54
And it shows a Root Object here.
-
5:56
It shows some references, so I'm able to traverse down into these references.
-
6:04
And in this case this 9 and 10 are no longer referenced.
-
6:07
Maybe at one point 5 had a reference to 9,
-
6:09
but at this point it doesn't so, it would be able to mark all of these.
-
6:14
And then, when it went through in the sweep pass would be able to say, well,
-
6:17
9 and 10, are no longer needed.
-
6:19
Now, if 9 and
-
6:20
10 had that circular reference that we talked about in the previous slide,
-
6:24
it wouldn't matter because, nothing from the Root, can actually touch them.
-
6:29
So it doesn't matter if they reference each other, they still would get
-
6:32
cleaned up, because there's no way to get to them from the Root.
-
6:37
So as far as tools go in my opinion Chrome has
-
6:39
the most comprehensive tools available to look at memory leaks.
-
6:44
IE11 however though,
-
6:45
has some really nice functionality going on in their memory profiling view.
-
6:50
And we're gonna look at both Chrome and
-
6:51
then and then some screenshots of how IE11 looks as well.
-
6:55
In Firefox, there's an about:memory view that can give you heap dump and
-
6:59
let you do garbage collection from there, force it.
-
7:02
There are some other extensions and scripts which I link to here,
-
7:05
if you come back through Presentation One later on you can take a look.
-
7:10
Safari it doesn't have a built-in tool to do it at this point,
-
7:14
but they do suggest using the Instruments Tool DevTool in,
-
7:19
in Mac OS X and here's how that looks.
-
7:22
There's a template for leaks.
-
7:23
You can actually attach it to the Safari browser or an iOS simulator, or
-
7:28
even an OS X application and, it can give you things like a heap dump.
-
7:32
Although it's, it's much further away from the JavaScript, so
-
7:36
it, it's a lot harder to interpret.
-
7:39
[BLANK_AUDIO]
-
7:41
So, let's talk about Chrome a little bit.
-
7:42
In Chrome there are three different tools that can, you can use to investigate
-
7:46
memory leaks, and I'll talk a little bit about why you would use each one.
-
7:51
First I'm gonna show some screen shots and talk about it, then I'll, then
-
7:53
I'll actually jump into an example where we can look at, at each tool in action.
-
7:59
The first is the timeline view,
-
8:01
and there's a number of things that you can capture here, but one is, is memory.
-
8:05
So, I can check this Memory option and I can hit Record and it will let me,
-
8:10
over time, see how the memory is growing in my application.
-
8:13
And so the memory time line is really designed as far as from a memory leak
-
8:17
perspective, it's designed to help you determine do I really have a memory leak.
-
8:23
I may be, the memory may be going up, but then eventually it may go back down.
-
8:27
It may just take some time.
-
8:28
So that memory timeline,
-
8:30
it's not as much to dig in as far as what's what's that memory.
-
8:33
It's more about do I have a memory leak.
-
8:38
This garbage can here you an actually force a garbage collection and
-
8:42
after you're done recording.
-
8:43
And again I'm going to jump into the tool in a second here I just wanna talk over
-
8:46
the screen shot.
-
8:47
After you're done recording you can actually look at a snippet of time here
-
8:51
and then you can dig into that a little bit and see, for example, they used
-
8:55
JS Heap during this time period, is going up and up and up, which doesn't look good.
-
9:02
The second tool is called the Heap snapshot, and
-
9:05
that will really be a dump of the entire heap at that time.
-
9:09
Now there is a lot of other stuff in there besides just the things you have created.
-
9:14
There is a lot of things that the browser uses, so it is somewhat
-
9:19
challenging to navigate, so in some ways you, you want to have some clues as far as
-
9:22
what to look for, you want to be able to search for some of the art data.
-
9:25
You want to be able to understand what, what applies to your application and
-
9:29
what doesn't.
-
9:30
The Heap snapshot will let you do comparisons between two Heap snapshots, so
-
9:33
that's what we're showing in this particular screenshot.
-
9:38
it, in this case it's showing you that there's some new objects being created.
-
9:42
You know, you could see if ones are being deleted, being removed.
-
9:45
You can see the size of some of those objects.
-
9:48
So the Heap snapshot's really that nitty gritty, you can really dig in and
-
9:51
see everything that's currently in the, in the Heap memory.
-
9:57
And then a newer tool in Chrome that's actually quite interesting is,
-
10:01
is called Record Heap allocations.
-
10:04
And, it's kinda like a combination between the memory time line and
-
10:07
the Heap snapshot.
-
10:09
So, it let's you record over time,
-
10:11
and it will be taking a series of snapshots as it goes.
-
10:16
And, the gray, the, the, I'll talk about the blue bar.
-
10:18
So, the blue bar, any time memory is allocated,
-
10:20
you'll see a blue bar indicating how much memory was allocated.
-
10:25
When that particular memory is recovered, it will turn gray.
-
10:29
So you can see all these gray bars in the past here.
-
10:32
That's all memory that was allocated, and then recovered.
-
10:35
So this, this is a view that really lets you dig into
-
10:40
things that happen over time in your application.
-
10:42
Maybe you're going through a work flow where you perform some action and
-
10:46
then you go back and then you perform that action again.
-
10:48
And you would expect to be at a steady state of memory.
-
10:51
The things that you, the, the, the objects you created while performing that
-
10:55
workflow, you would expect them to be recovered.
-
10:58
And this will help you understand when things are allocating and what's left.
-
11:01
So again, I can, I can actually zero in on a period of time here.
-
11:06
So I'm gonna jump into a quick example here.
-
11:10
And I bumped up the font of the DevTool, so
-
11:13
hopefully that'll, that'll come out clear.
-
11:15
And I'm gonna pop into a sample where,
-
11:18
really, memory is being allocated again and again over time.
-
11:22
And I can come in here and make sure memory is captured.
-
11:25
If I want to I can filter out some of the noise.
-
11:28
In this case I don't care so much about rendering and painting in, information.
-
11:33
I can hit Record and we can start to watch it.
-
11:36
It gives me some interesting information about timers being fired.
-
11:39
In my case what's happening is, is every second a timer's being fired and
-
11:44
it, and it's adding some objects to an array on the page.
-
11:49
So I can't actually, I can actually dig into one of these timers and
-
11:52
understand exactly, you know,
-
11:54
where that function is that's being called, which could be useful at times.
-
11:58
But what I can see here, is that memory is growing, and growing, and growing.
-
12:02
And mem garbage collection,
-
12:04
depending on the rate of that you're actually creating objects.
-
12:10
The garbage collection happens fairly often.
-
12:12
So it's not like you're generally going to have to wait seconds and seconds for
-
12:16
it to happen it's, it's happening quite often.
-
12:19
So I'm gonna stop recording here, and we can see the memory was going up over time.
-
12:24
Again, I can dig into an area of time on there if I want to.
-
12:27
Here, I can look at just a particular point in time.
-
12:31
And, I can do things like look at the number of DOM elements that are coming and
-
12:38
going in the page the number of documents, number of event listeners.
-
12:43
And then the use JS Heap in this case is what’s most interesting to us.
-
12:47
So it's going up and up and up.
-
12:50
So I send Marie a timeline again generally used to
-
12:56
used to identify that, hey I do have a memory leak.
-
12:59
Let's look at Heap's snapshot now so
-
13:01
if you go over to the Profiles tab of the DevTools you can take a snapshot.
-
13:08
And, I'm actually, and then once you have taken a snapshot,
-
13:12
this button here will let you take an additional snapshot.
-
13:15
And I'm gonna do that so we can look at a comparison.
-
13:18
So, there's several different views, there's Summary Comparison and
-
13:22
Containment, there is an additional view called Dominators that you can get
-
13:25
to by checking a flag in the DevTools here.
-
13:30
It's not particularly important for us to talk about today.
-
13:34
But if, if you're looking for
-
13:35
where that view is, you need to enable it in the, in that dialog.
-
13:40
So, the summary tells us everything by what type of object it is, so
-
13:44
the constructor of it.
-
13:47
Things that are in in parenthesis are really system, system objects, and
-
13:52
you'll see a lot of stuff here, you know, float32array, things like that.
-
13:58
And a lot of it is things the browser has created, the browser is using,
-
14:02
it's not stuff that you specifically decided to use.
-
14:06
In this case, I'm gonna dig, I'm gonna filter it by my_data.
-
14:09
And I can see that there's 20 20 objects here.
-
14:15
I can see the shell size that's, that's just how much each of those objects takes.
-
14:20
The retain size is that object and, and all of its references.
-
14:23
So really, if it gets removed, that all of that memory would be recovered.
-
14:28
So I can dig into my data and
-
14:29
I can look at, at each one of these 20 objects and see why it's being retained.
-
14:34
The distance here is that distance to that root.
-
14:37
So remember that diagram this would be the distance to that red,
-
14:41
that, that initial root.
-
14:43
And if I look a little bit in here I can see, that there's a window.current data
-
14:48
property and that's why this my data is being hung onto.
-
14:51
If I look at this one I can see see the, the distance now is three.
-
14:56
It's actually the previous property of current data and if I look at this one,
-
15:00
it's the previous property of the previous property of current data.
-
15:04
So I think you can kind of see what my problem is here.
-
15:06
If I jump down here, I'm probably gonna see a whole bunch of previous.
-
15:12
Yeah, so, you can kinda get an idea of why I'm having a memory leak.
-
15:17
My object's keeping track of its previous data, and
-
15:19
that's keeping track of its previous data.
-
15:21
So this, this would be how you can you use the Heap snapshot.
-
15:25
Now let's, let's look at Comparison a little bit so.
-
15:29
In the Comparison I can choose between snapshots, so
-
15:32
I'm not just two if I had many snapshots I could compare over time.
-
15:35
And I can see that there are eight new objects, eight new my data objects,
-
15:39
none were deleted.
-
15:41
And I can see some information about the size.
-
15:45
And then the final one is containment.
-
15:46
Containment is really those roots, remember we were talking about,
-
15:50
about the Root.
-
15:51
The ones that you're gonna want to concentrate is the Window Objects and
-
15:55
the DOM Trees.
-
15:56
There is some other stuff that's really more specific to the browser like
-
15:59
the GC Roots has, has other stuff in there that is not gonna be as helpful to you.
-
16:04
But if you dig into the Window Objects you can,
-
16:07
you can see things like things that are, that are hung on that window.
-
16:11
So in this case it'd be Current Data you can see that jQuery has
-
16:15
actually loaded the my data constructor.
-
16:17
And then all this other stuff is just Chrome just
-
16:21
features that are added on the Window Object.
-
16:24
Another interesting thing to look at is DOM trees, so
-
16:27
you can look at the current DOM trees and then Detached is really interesting.
-
16:31
Cuz this is stuff that you removed from the page, but it's still hanging around.
-
16:36
And in this case we can see there's three detached elements.
-
16:41
And, I want to point this out cuz we're gonna see it a bunch later.
-
16:45
jQuery actually at, when you load jQuery it actually adds a couple of things
-
16:50
DOM elements that are, aren't attached to fragment here and a div, a div.
-
16:56
These are,
-
16:56
you don't need to worry about these, you'll see these if you're using jQuery.
-
17:01
They are, they're not growing, they're not changing they're just there.
-
17:06
So that is the Heap snapshot.
-
17:08
And we'll come back to that in some of the later examples.
-
17:11
The last piece that I wanted to show is, that Record Heap Allocations.
-
17:17
Again, this is fairly new, but it's pretty interesting.
-
17:21
I can see, again, memory being allocated.
-
17:23
It would turn gray if it was being recovered but it's not.
-
17:27
And I can see that over time.
-
17:28
It's taking little snapshots, little snapshots over time.
-
17:32
And when I stop recording this is the fun part is that I can actually dig into,
-
17:37
you know, a particular slice of time and
-
17:40
I can see exactly what was allocated during that time and what remains.
-
17:44
Now if I were to,
-
17:46
if I were to look between, you know, would show me nothing here.
-
17:51
And when I get into some, you could see exactly what was allocated.
-
17:53
And it, and it's really not what was al, it's what's left.
-
17:57
So if these were turning gray, and
-
17:58
I hovered over it's really nice cuz it would show you nothing.
-
18:01
If this was recovered, you would see nothing.
-
18:04
Which is, which is really nice.
-
18:07
Okay, so
-
18:08
that's a little bit about the three different tools that you can use and,
-
18:12
and we'll jump into, into those a little bit further when we get to the examples.
-
18:16
I want to talk about Internet Explorer 11.
-
18:21
This is that same, same cage profile that same page where you're
-
18:26
looking at we can see the memory going up.
-
18:28
Again when you're recording, you can take snapshots over time.
-
18:32
One thing that's really nice in, in the DevTools, and just to point out,
-
18:36
this is under this little camera thing it's the Memory View of
-
18:40
the Internet Explorer 11 tools.
-
18:42
One thing that's really interesting and it's not as easy to see, but
-
18:45
this is actually a screenshot of the page at that time.
-
18:48
I found that to be really helpful to just get a,
-
18:51
get a bird's eye view of hey, what was I doing at that time.
-
18:54
Was I on the home page, was I on the billing page, where was I?
-
18:57
So that's pretty nice.
-
18:58
It tells you the amount of memory that was currently the page was using at that time.
-
19:03
And then it tells you a difference between the previous snapshot,
-
19:06
difference in megabytes of memory, difference in objects, and then, you know,
-
19:10
plus or minus.
-
19:12
So that, that's a pretty nice view.
-
19:15
When you jump into one of those snapshots, you can again navigate through the,
-
19:21
the things that are out there by types that would be
-
19:24
similar to Summary in Chrome.
-
19:27
Here I can see it by the Roots which would be like that Containment View.
-
19:32
One thing that's really, that I found really nice in Internet Explorer is that
-
19:35
they have an option to turn off a lot of the, the stuff that the browser creates.
-
19:40
So when, when I'm looking at this I'm really just seeing the stuff that I've
-
19:43
added to the page which, really helps to cut down on some of the noise.
-
19:47
So, Internet Explorer has some, has, has kind of cleaned it up in some ways.
-
19:52
I do think Chrome has more features across those three tools, but the,
-
19:57
some of the, some of the little touches they have in, in IE11 are quite nice.
-
20:02
and, and you can do a comparison again between the two.
-
20:06
So I'm comparing two snapshots here.
-
20:08
I can see difference in size, that type of thing.
-
20:12
Okay, so now we're gonna jump into a few scenarios that,
-
20:15
that I've encountered that have caused memory leaks.
-
20:20
And generally, what I've done is try to
-
20:23
strip down these down to the simplest form that you could possibly have.
-
20:26
So, I'm, I'm not gonna include Angular.
-
20:29
Not going a lot of stuff to give you scenarios to,
-
20:33
in those scenarios that would just cause maybe some confusion.
-
20:35
I wanna kinda narrow it down to a situation where you have some content on
-
20:40
the page, and then you're gonna remove it.
-
20:42
So on a single page application, a lot of time what you're doing is you're rendering
-
20:46
some type of view, and then eventually the user wants to do something else.
-
20:50
So you clear it, and then you render something else.
-
20:53
And that's a case now, when I remove all those elements.
-
20:56
That's a case a lot of the times where there can't be a memory leak.
-
21:00
So, the first one I'm going to look at is related to Bootstrap.
-
21:03
So if you were around yesterday, you saw Bess's great talk on, on Bootstrap.
-
21:08
I'm sure many of you have used it.
-
21:12
And when using Bootstrap one of the features we
-
21:14
were using was the affix functionality.
-
21:16
And that allows you to sort of have a, a, an element that's fixed on the page.
-
21:22
And the way you do that is you can, one of the ways you can do it is just to
-
21:25
declaratively add some data dash attributes,
-
21:27
and that will signal Bootstrap to say, hey go ahead and affix this.
-
21:33
Then I have a button on the page that I'm just going to remove this element.
-
21:37
So again I'm simulating that single page app where we're gonna remove something,
-
21:41
put in some different content.
-
21:43
And I'm gonna jump back over to the example here bring up this affix and so,
-
21:48
you know, as I'm scrolling you can see this header stays in place.
-
21:52
A lot of examples are,
-
21:53
are really bare bones if not, trying to really style them or something.
-
21:58
But here when I clear out that content at this point I would expect hey
-
22:01
that table's gone.
-
22:03
And we can move on and render a different view.
-
22:06
So I'm gonna take a heap snapshot here, and there's,
-
22:08
there's a few ways we could look at this but I kinda like containment for this.
-
22:12
And I'm gonna jump into detached dom nodes and ouch.
-
22:17
Now I see that three, you know,
-
22:18
now this is that jQuery stuff I said don't worry about that.
-
22:21
So that's fine.
-
22:22
But I look at this, I see 7,025 detached dom nodes.
-
22:27
Wow, and when I drill into that I, sorting it by distance is quite helpful
-
22:33
because generally what's hanging onto it is the thing that's closest to the root.
-
22:38
And so I, I see there's an html table section element.
-
22:41
If I hover over it, I can see some of the properties on that element,
-
22:45
I can see it's got a fixed top on it.
-
22:46
And I can see it's that t head so indeed it's the one that I put that data-spy.
-
22:54
So when I look at this one other thing about the color coding, so
-
22:59
if you see an element that is coded in
-
23:02
red that means it has no direct reference to it from JavaScript.
-
23:06
If you see something in yellow that's really where the reference is.
-
23:09
So in this case there's no direct reference to this html, this, this T-head.
-
23:14
But there is something holding on to it.
-
23:17
So when I click on it,
-
23:18
when I click on one of these elements, I jump down in this retainer section and
-
23:22
that's where I can really drill in and see what's holding onto it.
-
23:26
I can see that it's a dollar element.
-
23:28
It's represented inside of a dollar element variable, I mean, a fixed object.
-
23:33
I can see that it's being used as the context for some function, and in this
-
23:38
case it looks like a jQuery proxy function that really forces the value of this.
-
23:45
And if I drill a little bit deeper I can see, oh there's some type of click event,
-
23:48
and okay there's a scroll and a click and a load event.
-
23:52
It sounds like window events.
-
23:55
And so at this point, you know, I personally haven't attached any window
-
23:59
events related to affix, I just put that data by and let Bootstrap do its thing.
-
24:05
So when we dug into it a little bit more inside the Bootstrap code.
-
24:10
We found that it was adding some.
-
24:14
That hammers to the window.
-
24:15
So the default target in this code happens to be the window.
-
24:18
And I remember Dave mentioned this yesterday in his jQuery talk.
-
24:21
You know, this is what's called a namespace event.
-
24:25
So scroll is the event, and the other stuff is
-
24:28
just a namespace which could help you actually remove it if you want to.
-
24:32
So that's what we found in the bootstrap code.
-
24:36
And just little, little reminder about how to remove events in jQuery.
-
24:42
Let's say I'm adding an event, and the name of the event is event and
-
24:44
the name space is our name space.
-
24:47
I'm adding some handler, some function I have.
-
24:49
There's a couple of ways that I could remove an, an event in this way.
-
24:54
If I just say $window.off("event.namespace"),
-
24:56
it would remove all for this event plus namespace.
-
25:01
So if, if, if I know that hey, this is my thing, I put my namespace on it, I've got
-
25:05
one instance of it or every instance I, I, it's okay with removing those events.
-
25:09
That's great, you can just use that.
-
25:11
If you do have access to the original function that was bound.
-
25:15
You could just to window.off with the event, and you know, that handler.
-
25:20
In our case with Bootstrap we really don't have access to the functions that
-
25:23
they use.
-
25:23
In fact, they wrapped it in a proxy call which means we,
-
25:27
nobody has access to that function directly.
-
25:30
And finally, if we don't include the event,
-
25:32
if we just say .namespace it would remove all events for that namespace.
-
25:37
And so again this was the code we saw in Bootstrap.
-
25:41
And we found that Bootstrap did not have a destroy method or,
-
25:45
or a way for us to actually remove those events.
-
25:48
So in our code, you know, we were doing more data binding so
-
25:52
it didn't look exactly like this, but in our code we
-
25:55
actually do an off without the event name, so it got all of the events.
-
25:59
And remove them ourself.
-
26:00
Like I said,
-
26:02
ideally, you know, ideally Bootstrap would, would provide that functionality.
-
26:06
You know, but, but they didn't so we, we had to take care of that.
-
26:12
And this comes down to sometimes,
-
26:14
like I'd said earlier, sometimes in these third parties that you're using you want,
-
26:17
the way you're using it is not necessarily intentional of the way it was created.
-
26:22
So so in this case we had to go into the library and figure out what it was doing,
-
26:26
then figure out what we needed to remove.
-
26:31
We found a similar thing when I was code reviewing a project with
-
26:34
sticky table headers, similar functionality, but it was adding
-
26:37
scroll resize events to the window and that was hanging on to the entire table.
-
26:42
In this case, the sticky tables headers had a destroy method that we could call.
-
26:48
That's a pretty standard convention in jQuery plugins.
-
26:51
Call that destroy method and that took care of it for us.
-
26:55
You know, if you're pulling in third party code it's good to think about not just,
-
26:58
hey, what does this thing do for me, what problem does this solve,
-
27:01
but is this thing gonna play nice in the environment that I have it?
-
27:05
Does it have a destroy method or a way to dispose it?
-
27:07
It's definitely something to consider when pulling in third party code.
-
27:12
So we call that destroy method.
-
27:13
That took care of it.
-
27:17
Scenario number two talk a little bit about Globals.
-
27:20
So won't spend too much time on it, but I think the,
-
27:25
the guidance that everyone has received regarding JavaScript for, forever now,
-
27:29
has been, you know, be careful about creating global variables.
-
27:33
As far as memory management, it's the closest thing to the root.
-
27:37
It's, it's not gonna go away.
-
27:39
If it's a global variable, or a reference by a global variable,
-
27:43
it's not going to get cleaned up.
-
27:46
So the code here is not too important.
-
27:47
Let's say I have some view object that, that I'm creating the instance of.
-
27:53
And I'm just doing this on a page or in a file that's referenced by a page.
-
27:57
When I look here, this MyView, it's gonna end up on a window.
-
28:01
And so is this app, so window.MyView, window.app,
-
28:04
those are gonna be on the window, they're not going to get removed.
-
28:11
So what can we do about that?
-
28:12
Well enter the IIFE.
-
28:14
Immediately Invoked Function Expression.
-
28:16
There are certainly other ways to handle it too,
-
28:18
but I'm sure that people have seen this in code or, or you're likely are using it.
-
28:24
It's a way to create a scope where, where variables inside of this are going to be
-
28:30
attached to the surrounding scope, which in our case would've been the window.
-
28:34
And so this is,
-
28:34
this is a function, and that function, we're gonna call it right away.
-
28:39
And if you wanna put your paren outside, you know, that's fine too.
-
28:41
It's, it's not important, some people it the other way.
-
28:45
So in our case one thing we could have done in that previous example,
-
28:48
we could have wrapped our code here in that IFFE novice my view in this app.
-
28:52
They wouldn't be on that window and
-
28:54
they would go away as long as nothing's referencing it.
-
28:59
You may be using jQuery ready block.
-
29:04
One of the forms of that would be, you know, dollar and passing a function in.
-
29:09
And, and that would, it's inside of that function as well,
-
29:12
so it'd still perform the same role that the IFFE would.
-
29:17
In the jQuery readies case,
-
29:18
it would just not execute that code until the dom content has loaded.
-
29:25
So in Blazon.
-
29:27
I, I know that you're familiar with Blazon now if
-
29:29
you've been watching the presentations, presentboldy.com.
-
29:31
I encourage you to try it.
-
29:33
It's a great tool.
-
29:35
A while back we found a, a.
-
29:38
Well, a bunch of dom nodes were leaking in Blazon, and
-
29:42
what it came down to was a tooltip library we were using called OpenTip.
-
29:46
And we were databinding against OpenTip, say,
-
29:49
tooltip next slide there's a bunch of tooltips in Blazon.
-
29:53
So any iconic button that you have on the screen, you can hover over it and
-
29:57
see that great tooltip.
-
29:59
And as we were navigating through slides we found out that, you know,
-
30:02
anything attached to these tooltips was just hanging around.
-
30:05
And when we dug into it more, what we found is that,
-
30:08
you know, it wasn't as complicated as it might seem.
-
30:12
Really, OpenTip was globally keeping track of all of the tooltips.
-
30:16
It had an array called OpenTip.tips and every tool tip created was added to it.
-
30:22
And there was no code to actually remove it.
-
30:24
It wasn't part of OpenTip.
-
30:25
Again, this comes back to the use case.
-
30:28
OpenTip didn't realize it would be in this scenario of a single page app
-
30:32
where you're coming and going with these tooltips.
-
30:36
So in our case, you know, the code here is not super important.
-
30:39
Just that we had inside of our custom binding.
-
30:40
We were creating a tooltip, and then later we actually added a disposal callback and
-
30:46
we had to remove the tooltip from Opentip.tips which was a global
-
30:52
array that was keeping all the tooltips.
-
30:54
Based on our binding we also had to know all term references,
-
30:57
but it's just a case where adding things to a global may be convenient but it,
-
31:04
it has other effects like hanging on, on to hanging on to that memory.
-
31:09
So you know again OpenTip probably should provide a way to remove that.
-
31:15
Okay, moving on to scenario three.
-
31:16
Closures.
-
31:17
Closures, closures.
-
31:20
Closures are.
-
31:22
We've already seen it some of the examples I've shown.
-
31:24
Closures really are one of the major sources of memory leaks.
-
31:29
And the thing about closures is this, we use them all the time.
-
31:32
We use them every day, we don't hardly even think about them.
-
31:35
We don't generally think, I'm creating a closure right now,
-
31:38
we're just creating functions and we're going from there.
-
31:42
The thing to remember is that from a memory standpoint it
-
31:45
really can carry a reference just like you're setting a property to some value.
-
31:51
If a function is using a variable that's outside of it's scope, you know,
-
31:55
that will be considered a reference.
-
31:56
[SOUND] You know, just a, just a brief example on closures here.
-
32:01
You know, I have this person constructor and
-
32:04
inside it I have a shoal message function and
-
32:07
it's alerting this message variable and the main argument that gets passed in.
-
32:12
And so I've created a new person called me and I can now call me.showmessage.
-
32:19
And so what's interesting about closures is that it's not just about what's in
-
32:23
this function, it has access to this message variable,
-
32:28
it has access to this name argument.
-
32:31
And not copies of them.
-
32:32
It's not a copy of message.
-
32:33
It's not a copy of name.
-
32:34
It can still access those, the actual variable.
-
32:37
So if I had another method that changed the message variable,
-
32:41
it would be reflected when that, that was called.
-
32:45
So I won't spend too much more time on closures,
-
32:47
but I do wanna really recommend the Scopes and Closures book by Kyle Simpson.
-
32:52
It's, it's online for free or you can buy it @getify if you've heard of,
-
32:55
of him through his Twitter handle.
-
32:57
It's part of his you don't know JavaScript series and it, it really is,
-
33:01
to me at this point, may be the definitive reference on, on scopes and closures.
-
33:07
I forgot my joke.
-
33:08
I was gonna say you know, I was gonna talk more about scos, closures.
-
33:12
But it's out of scope for this presentation Okay,
-
33:17
let's talk about a specific scenario.
-
33:21
Let's talk about our basic scenario here.
-
33:23
So I'm gonna come back and bring up
-
33:28
Flip back to the code real quick.
-
33:33
So, I'm using jQuery here.
-
33:35
We could be using raw DOM functions as well, but
-
33:38
I know that everyone is pretty familiar with jQuery, so
-
33:42
we're gonna use it to ease some of the burden of cross-browser support.
-
33:47
And one of the things you're told in jQuery, you know, cache that selector.
-
33:50
You know, selecting some elements.
-
33:52
Don't do that again and again.
-
33:53
Cache it.
-
33:53
So I created this variable dollar l.
-
33:56
It's just an element, my ID on the page.
-
33:59
And now I'm creating a click handler.
-
34:01
I'm updating the text when you click on it,
-
34:03
and when you, when you click the clear button, and I'm removing it.
-
34:06
So I had to use dollar l a few times.
-
34:09
Seemed like caching it was a good idea.
-
34:12
but, let's see, let's see what happening here.
-
34:17
So I open this up, and I'm gonna clear that, so I'm removing it.
-
34:20
I'm just taking a snapshot.
-
34:21
And let's go into, detach DOM nodes.
-
34:26
Again I see my jQuery stuff that I'm okay with, but here I have a div.
-
34:32
If I hover over and I can see, yep that's my testing div.
-
34:36
It's being held onto for some reason.
-
34:39
And if I look down in here I can see well it's the dollar l variable,
-
34:43
inside of some function.
-
34:45
And what is this function?
-
34:46
Well, it's that dollarl.remove from there.
-
34:50
Okay, so if I flip back over, I can see.
-
34:52
Yeah, you know what this, this event handler is still attached to that button
-
34:57
and now that dollar l is being hung onto, and since it points at that
-
35:02
jQuery wrapper to the element, that element can't actually go away.
-
35:07
So one tip here.
-
35:08
You know if I, I, I can actually name functions.
-
35:12
So even in a like a function I've created anonymously here, I can give it a name.
-
35:17
And that's really helpful in stack tracing and, and tools like this.
-
35:23
So here's an example, I'm going to do this again.
-
35:26
But I've named that function.
-
35:27
And let's just take a look quick at that snapshot.
-
35:31
Called the containment and detach DOM nodes.
-
35:35
It's and look at this div again.
-
35:37
See now it doesn't say anonymous function.
-
35:39
Now it says my remove function.
-
35:41
You know, it's really helpful for trying to understand,
-
35:43
you know, what are these functions that are getting passed around.
-
35:47
That are, that are holding to these variables.
-
35:49
In stack traces it's really helpful as well, but in this type of scenario it,
-
35:54
it helps us get some clarity on what that function is.
-
35:56
So we showed how
-
36:02
you can name that function now how would we how would we clear up this memory leak.
-
36:06
Well the easiest way probably is that we we could set dollar l to null
-
36:11
and so, why, why does that work?
-
36:15
Why are we doing that?
-
36:16
Well, we're always gonna to have a reference to dollar l, but dollar l
-
36:20
doesn't always have to have a reference to that element that's not getting removed.
-
36:26
If I set it to null, you know, this, this function still has reference to l,
-
36:29
but dollar l is just not the element.
-
36:31
Of course, we probably wanna check that dollar l exists before calling remove if
-
36:36
you clicked it multiple times.
-
36:38
So that's an easy way to clear up that leak.
-
36:42
But I want to talk about something now, the delete keyword.
-
36:45
So, we set it to null but I'm sure you've heard there's a delete keyword.
-
36:49
We've used it in JavaScript.
-
36:51
Should we have just deleted the variable, wouldn't that kind of nuke it so
-
36:54
dollar l didn't exist anymore?
-
36:57
Well the delete keyword is not intended to be used on variables.
-
37:01
So if I create a message for
-
37:03
variable I deleted and then I log it out it's still there.
-
37:08
Delete keyword doesn't work on variables.
-
37:09
It's not supposed to.
-
37:11
Delete keyword can be used against properties.
-
37:15
So you know I can do delete data.name.
-
37:18
And then I can do typeof data.name is undefined.
-
37:22
So that's where it can be used, but you really wanna be careful with it cuz it,
-
37:26
it can cause some major issues with optimization.
-
37:29
I would like to show that really quick here cuz I think that it,
-
37:32
I found this really interesting.
-
37:36
Let me flip over here.
-
37:38
So let's say I have these my thing objects with a name and an ID.
-
37:42
And let's say I have a function called clearName.
-
37:44
And the thing about this clearName function,
-
37:46
there's two different implementation of it.
-
37:48
One I'm going to set it to null, and one I'm going to delete it.
-
37:51
Delete the property.
-
37:53
And I thought this was fairly interesting.
-
37:56
So when I, when I do this I'm gonna allocate a a thousand of those and
-
38:00
then and I'm gonna clear the name.
-
38:03
And take a heap snapshot.
-
38:07
So actually summary is good.
-
38:10
I'm gonna look at my thing here.
-
38:13
I can see 1,000 of them.
-
38:14
I can see that shell size, that contain size if I dig in.
-
38:17
I can see 20 bytes, 20 bytes, you know.
-
38:20
Not very much memory it's taking up, you know, if I hover over one,
-
38:24
I can see that it's id1.
-
38:26
I can see the name is null.
-
38:28
Now, if I do the delete.
-
38:32
So if I actually delete that name property when I'm creating these objects and
-
38:37
now if I do a snapshot, thought this was fascinating.
-
38:41
Look at the size now.
-
38:42
12,000 channel size cuz I really deleted that property now.
-
38:46
Look at the retain size, 424,000 bytes.
-
38:49
Look at each one here.
-
38:50
12 and 424 instead of 20 and 20.
-
38:54
So by deleting properties off of that object you've really messed up some of,
-
38:59
of V8's optimizations and could be the same in other browser as well.
-
39:03
Now just a little bit about delete and how it can be a little bit dangerous for
-
39:07
as far as optimization goes.
-
39:09
But the delete keyword, I don't wanna say,
-
39:12
don't ever use it cuz there are some interesting uses for delete.
-
39:15
Generally you could use delete when you want to remove a property such that you
-
39:20
can't iterate through the properties of an object and
-
39:22
find it or use hasOwnProperty to find it.
-
39:25
Or, you know, when you want to differentiate between a property
-
39:28
existing versus having a value of undefined.
-
39:32
So if I have an index object here with someId as undefined.
-
39:35
I have Index 2 as an empty object.
-
39:38
If I just look at the type of each of them it tells me undefined and
-
39:42
that's not very helpful.
-
39:43
I can't tell the difference between whether someId was even in there.
-
39:49
Now I could do someId in index, you know, that would tell me the exact property can
-
39:53
I iterate if I was iterating through would I find it?
-
39:55
That's true.
-
39:56
You know, I might wanna do has own property instead because.
-
40:00
That would get just things on an object, not on its prototype.
-
40:04
For example, toString I could find, in, you know, if I was doing that on index,
-
40:09
I would find toString, so so my, my point is that if you do want to use delete it
-
40:14
still, it still is okay to use it in situations like this.
-
40:17
Perhaps you have a long running index where things are coming and
-
40:20
going, keys are coming and going and you really don't want it to
-
40:23
end up with thousands of keys where most of them are undefined and
-
40:26
when you iterate through them you'd have to throw out the undefined one.
-
40:29
So delete in that case is still a very valid,
-
40:31
that's the very valid way to use it.
-
40:35
Okay, a little bit about references and closures.
-
40:37
So I made a change to the code we were looking at before and here's the change.
-
40:43
I am not using dollar L down here anymore.
-
40:45
I'm not using dollar L in our remove function.
-
40:47
Remember that was our problem.
-
40:49
It was hanging on to dollar L,
-
40:50
well if I don't use it then we should be good, right?
-
40:55
Well it can be browser dependent, but in some cases.
-
40:59
But in Chrome for sure, and in IE all of the functions that are created within this
-
41:06
scope seem to have some level of sharing of the variables that they're closed over.
-
41:11
So even though I'm not using dollar L, it's still,
-
41:14
it's still is, considered a reference of this function.
-
41:18
And interestingly in chrome, if I were to comment this out, comment out the click or
-
41:23
even just comment out that dollar L dot text,
-
41:27
now even though I created that variable, It's not actually included so
-
41:31
in my opinion I want to kind of rely on these tricks.
-
41:34
I want to make sure that you're safe in all browsers.
-
41:38
So how can we do that?
-
41:39
Well in this case one thing we could do is move our block out of the IIFE.
-
41:45
You know if I move it down here it has no chance to access [UNKNOWN],
-
41:48
no chance to use it.
-
41:51
Of course we could just not use a variable there you
-
41:53
know if we don't need to cash in.
-
41:56
Maybe we could do it that way.
-
41:59
One of the things that I do most often is try to create functions you know,
-
42:05
maybe it's not just hanging out here globally but
-
42:09
create a function to handle what I want to do and then pass that function directly.
-
42:15
So, try to avoid anonymous functions when I can, and,
-
42:17
only include the things, you know, the things that I need.
-
42:23
So, this would be another way to not include dollar L in that function.
-
42:29
And finally you know,
-
42:31
once we call that clear we don't really need that event handler anymore.
-
42:36
So what we could do is we could remove that event handler.
-
42:38
So in, in the code down here we could do an off or
-
42:42
something like that but in this case I'm choosing to use one.
-
42:46
That's not a typo, I didn't mean to use on.
-
42:48
One is a convenient way to do a one time event handler, you, it'll call it
-
42:53
when you click on it and then it'll automatically remove it for you.
-
42:56
So, I found that to be kind of useful for sort of that one time situation.
-
43:01
Now this one has, has got me before several times.
-
43:04
I don't even want to admit it, how many times this has actually got me.
-
43:09
Be very careful if you're investigating memory leaks.
-
43:11
Be careful about what you're doing in the consult.
-
43:14
If you're logging out elements or objects, and they're sitting there on the console,
-
43:19
they're not getting removed, even if they could be.
-
43:22
So, I've had cases where I'm investigating memory leaks and I am
-
43:27
trying to do some logging to understand when things are getting created,
-
43:30
when things are getting disposed.
-
43:31
What element is that?
-
43:33
Where is that?
-
43:34
You know, maybe I logged out the parent to see where this thing is getting rendered.
-
43:37
If it's in that console it actually won't get released and
-
43:40
you can start setting everything you think of to null and it still won't get removed.
-
43:45
So just as part of an investigation be careful with that console.
-
43:50
In the use of eval, eval, you know,
-
43:53
I really don't think there's a lot of great uses this for eval at this point.
-
43:57
If you have a bunch of [INAUDIBLE] string you gonna wanna do [INAUDIBLE] You know,
-
44:01
if you want to dynamically access a property you should be using,
-
44:04
you know, the syntax where accessing the property [INAUDIBLE] so,
-
44:09
eval is not you know, something you should, if you are using eval,
-
44:15
you may wanna rethink while you're, while you're doing that.
-
44:18
But the interesting thing here is that if I eval, even in this case,
-
44:21
I'm just evaling an empty string that does nothing.
-
44:24
But if, if the optimizer sees eval,
-
44:26
it say I may need all the variables that I could possibly access here.
-
44:30
So Dollar L actually gets included, in this closure, because, it doesn't know,
-
44:35
even though this ecstatic text, mabye it should know but,
-
44:40
yeah, eval is [UNKNOWN] definitely a good way to go.
-
44:42
Yeah, I could see, you know, ligament use of eval mabey some type of data binding or
-
44:47
something you have in an element.
-
44:48
[COUGH] You know,
-
44:49
where you actually gotta take some text and turn it into some job script object,
-
44:54
or, code, but, you definitely would want to isolate that as much as possible.
-
45:01
Okay, scenario number four, this is gonna be quick.
-
45:05
Timers and parent child links.
-
45:07
So that first sample we saw in the timeline,
-
45:09
where we saw its memory growing and growing.
-
45:11
This comes from a real sample from a code review.
-
45:14
Two things to remember,
-
45:15
if you starting timers or intervals, the code here is not too important I think.
-
45:19
This is a little more interesting.
-
45:23
If you're starting the timer on interval, and
-
45:26
then it's possible that you're going to be removed before that timer comes up,
-
45:31
you know, be sure to keep track of the idea of the timer or
-
45:34
the interval and then call clear time out or clear interval.
-
45:38
So if you're creating some reusable thing and you're adding some timer, maybe you're
-
45:42
watching resize or you're, you're doing the eject request,make sure you
-
45:46
clear out those timers coz, coz they're a major source of memory leaks as well.
-
45:53
And then, you know, this is nothing special.
-
45:55
Remember we saw that previous, previous, previous, previous.
-
45:58
You know, be careful with parent child links and
-
46:00
cascading links, to things like that, you know, that burned us.
-
46:04
Burned the project in this case,
-
46:05
but it, just, just make sure you careful about how things are linking like that.
-
46:11
Scenario number five, this is the last of the scenarios.
-
46:15
So now Doug yesterday talked a lot about messaging and subscriptions.
-
46:19
One thing to note.
-
46:20
And, and this is kind of similar to events that we've talked about already today but,
-
46:24
in the observer pattern or
-
46:25
in pub/sub, which we'll, which I'll bring up as well here.
-
46:30
When I'm doing something like item type subscribe,
-
46:33
passing in myHandler and my context.
-
46:37
What happens is that item type some other
-
46:40
variable somewhere else has a reference back to me.
-
46:43
So I'm creating my object yay and then, I'm subscribing to this item type thing.
-
46:48
It has a reference back to me.
-
46:49
If I don't type lives longer than I do.
-
46:53
I can't go away as well, coz it links to me.
-
46:55
Same with pub/sub.
-
46:56
I mean, amplify.subscribe, amplify, a library that, that appendTo has
-
47:01
written to, that, that can do some pub/sub among, amongst other things.
-
47:05
And here I have a topic and again, passing my this and someHandler.
-
47:09
Amplify is definitely going to live, a lot longer than,
-
47:11
than my object that I'm creating.
-
47:15
So in that case if I don't unsubscribe,
-
47:18
I can never be cleaned up until that subscription is removed.
-
47:22
So let's say I had a basic view and somewh, the requirement
-
47:28
I had was hey when there's a session time out, I need to set active to false, so
-
47:33
I can subscribe to some session timeout topic and then set it to false.
-
47:38
That's great, that solves our problem, we're decoupled, you know we have that
-
47:42
subscription and but again amplify's going to
-
47:47
hold onto that reference to the view that I create forever unless I unsubscribe.
-
47:53
So it's something to be mindful about.
-
47:57
A few lessons learned from some of the situations I've seen.
-
48:00
Be very careful with integrating third party code.
-
48:02
Talked about it at lunch today but you know the way you're using it may
-
48:06
not match the author's intention and it certainly is fine to post issues and
-
48:09
try to go back and forth and try to improve that library as well.
-
48:12
But just be mindful that when you're pulling in dependencies,
-
48:15
don't just look at what it can do for you.
-
48:17
Make sure it fits into the scenario you want to use it and
-
48:20
make sure you can clean it up.
-
48:22
Be mindful of globals I'm not gonna see any more out there
-
48:25
I think everyone's pretty aware of, of how that would work.
-
48:29
earlier, when you're creating reusable pieces of code,
-
48:32
whether you call it modules, components, bindings,
-
48:33
directives, whatever you're creating, you know, think about life cycle, don't just
-
48:37
think about I need to put this date picker on the page, I'm gonna create a directive.
-
48:41
Think about what it means to remove it from the page.
-
48:44
Do I need to call destroy, what exactly do I need to do?
-
48:46
If I've created a timer or an interval,.
-
48:49
If I added a Window event, make sure I can remove it.
-
48:52
If I'm doing things like adding Window events, don't, you know,
-
48:55
use name space [INAUDIBLE] jQuery, or
-
48:57
keep track of your handlers, you can directly remove that handler.
-
49:01
It's all things that, that you should think about.
-
49:04
Just, just like the functionality you're creating.
-
49:06
Think about it as far as how it's gonna get destroyed, as well.
-
49:10
Login and instrumation, instrumentation are really useful.
-
49:14
Sometimes you may want to stringify your objects, so
-
49:17
it's not actually holding on to the actual object.
-
49:20
Just a string representation of it.
-
49:22
Or potentially build new objects with just the little pieces that you do want to log.
-
49:27
You don't really want your logging to, to be the thing that causes the memory leak.
-
49:33
Okay, quickly here.
-
49:35
Clean up time.
-
49:38
So I just wanted to point out a few libraries out there.
-
49:41
I'm just gonna ask the chat right now to tell me, as far as the,
-
49:44
the projects, does anybody use things like Knockout, Angular, Ember, Backbone React.
-
49:49
Is anybody using any of those libraries today in their apps?
-
49:53
[SOUND] I'm gonna,
-
49:54
I'm just gonna quickly go through some of the way that you can do disposal in these.
-
49:59
So knockouts are what I'm most familiar with.
-
50:01
If you're in custom bindings and, and really my intention here is that you
-
50:04
can come back and review these slides so I'm just gonna cover them really briefly.
-
50:07
If you're inside a custom binding you can add a dispose callback to the elements.
-
50:12
When that element gets removed you can run some cleanup code.
-
50:15
If you happen to create a computed observable in a custom binding,
-
50:19
you can add an option to say, remove this for me automatically.
-
50:23
Dispose of this automatically when you, when the element's removed.
-
50:27
If you're creating computed observables or
-
50:29
subscriptions you can manually dispose of them, if you need to.
-
50:32
And generally, when you wanna do that is when you're subscribing to
-
50:35
something that lives outside of your object.
-
50:38
Let's say, on my view model, I happen to subscribe to something on the app.
-
50:42
I may need to run dispose because again app has that link back to me,
-
50:47
and I can't be disposed, I can't be cleaned up until that link is broken.
-
50:52
Angular has some destroy events.
-
50:55
So, like on, on, on any scope, you can subscribe to that destroy and
-
50:59
do things like cancel timers.
-
51:01
Elements that actually fire a destroy event,
-
51:03
as well so another scope of the element if you're in a directive,
-
51:07
you could potentially be cleaning up something like a date picker.
-
51:13
Ember. I know Ember the least here.
-
51:14
I've done just a minor bit of work with it.
-
51:17
There are some component life cycle hooks will clear render we'll destroy all
-
51:20
mention of the ones to look for.
-
51:22
One is called whenever it gets re-rendered.
-
51:25
One is called when it's actually going to be destroyed,
-
51:28
so those are two hooks that you can use to do clean up.
-
51:31
In backbone, a while back it would be more common to
-
51:34
see things like this.model.on change an color code.
-
51:39
Again this is exactly like the subscriptions when you do this.
-
51:42
Desktop model has a reference back to you.
-
51:44
And so what you need to do is make sure that you're calling off.
-
51:48
But in, in more recent versions of Backbone, .9.9, was,
-
51:52
0.9.9 was when it was added, there's a new API called listenTo.
-
51:57
That kind of flips it around.
-
51:58
So instead of seeing this step model about all of it, you can say this.listen to,
-
52:02
pass in the model, the change and, and the handle you want to run.
-
52:06
Under the covers, it still does that subscription that was previously being
-
52:09
done, but it's able to keep track of it.
-
52:11
So it removes it automatically for you.
-
52:14
And, if you need to you can use this stoplistening API to force it as well.
-
52:20
So in Backbone be careful about the subscriptions you're making and
-
52:23
listen to will help some of that automatically.
-
52:26
In the events that you add in a Backbone to use those will automatically be
-
52:31
removed as well.
-
52:33
React is picking up a lot of steam right now.
-
52:35
I expect to see a lot more out of react and future times here.
-
52:40
Component will unmount their life cycle method, life cycle event that gets called.
-
52:44
Here's where you can do cleanup for React component.
-
52:49
So as far as the future of memory leaks in modern web development, I think,
-
52:52
I think there's a bright future.
-
52:53
Browsers are always improving and frameworks, the libraries are maturing and
-
52:57
a bit reason for that is because the tools, tools keep improving.
-
53:01
And it's just a cir, it's a circular thing as the tools improve you know, you're able
-
53:05
to eliminate more and more leaks from these different libraries and frameworks.
-
53:08
And also people are more aware of the type of things I talked about today.
-
53:12
People are more aware of closures, people are more aware of removing event handlers,
-
53:16
that type of thing.
-
53:18
And new language features in es six.
-
53:19
There's something called weak map it's basically a hash where the keys do not
-
53:22
have to be strings.
-
53:24
You can actually use a dom element or, or an object as the key but they don't
-
53:29
hold onto that memory so they, they won't prevent something from being cleaned up.
-
53:35
And that's it. I'd be happy to stay around and chat.
-
53:37
And I'll post a link to this presentation in there but
-
53:40
I hope that you can start taking a look at your applications and, you know,
-
53:45
fingers crossed that you don't have thousands of detached arm elements.
-
53:50
But yeah, definitely give it a shot.
-
53:53
I'd love to answer some more questions if you have them.
-
53:55
And thanks for having me at Modern Web Conference.
-
53:59
>> I think a bunch of us were saying that this was like really a 600 level talk.
-
54:05
So, this was amazing.
-
54:06
I think a lot of minds were blown.
-
54:08
I had one question that I, I was able to, able to grab, I wanted to ask.
-
54:12
Somebody was, I forgot who, I apologize, I didn't capture that.
-
54:15
Was wondering if is there some memory leak difference be,
-
54:19
using single quote versus double quote for strings.
-
54:22
>> No, no, not at all.
-
54:23
>> If any of you have >> Not to my knowledge anyways.
-
54:28
[LAUGH] >> I didn't think so either.
-
54:30
I didn't see any other questions, or I didn't capture them, I'm,
-
54:33
I might have missed them.
-
54:38
if, Laura S has a question.
-
54:41
So you would not recommend dollar sign dot remove for huge element blocks?
-
54:46
>> Well really the issue is, is, is that.
-
54:49
So I had something inside that block that had a,
-
54:52
that, that was held on to by something outside of it.
-
54:54
So what it was, it was a window event.
-
54:56
So when I added that window event,
-
54:58
the window, or actually add a link back to something inside that block.
-
55:01
So it's okay to remove it, but if, if everything is self-contained,
-
55:05
if all the event handlers are inside that block, it'll get cleaned up automatically.
-
55:09
But it's just the fact that we add something outside that we
-
55:11
were subscribed to.
-
55:12
It could be Amplify, it could be a Window event,
-
55:14
it could be something outside that's pointing back to us.
-
55:17
That's a lot of the cases where, that problem comes in.
-
55:21
The one other thing I just would say is that.
-
55:23
You know, if some of those, those stack traces some of the digging into that
-
55:27
looks kind of complicated, I mean it, it is a bit hard to interpret,
-
55:31
I mean I'm not saying I'm an expert in interpreting it.
-
55:34
I think the, the best thing I can say is it takes some trial and
-
55:37
error and it, you just kind of have to get into the right area,
-
55:39
to say oh, okay, it's a scroll event let me start looking into that.
-
55:43
You don't have to really just dig into and
-
55:45
say there's the leak I'm gonna just go fix it right now.
-
55:49
It rally just gives you kind of the ballpark of what I should start looking at
-
55:52
In some case it would take some trial and error.
-
55:54
I don't think any of us wants to just start setting everything to null.
-
55:57
You know I don't want to add extra code setting every variable to null
-
56:01
all the time so it, it takes a little trial and
-
56:03
error but you know just it gets you in the right ballpark
You need to sign up for Treehouse in order to download course files.
Sign up