 I'm going to give a quick talk about memory leaks in JavaScript. So I'm going to jump right in. I'm going to talk about what is a memory leak. So now we know that your code, when you create variables, when you create objects, this takes up memory. This has to be somewhere. So it's going to be inside your ram or memory. Now, since we're talking about JavaScript, our runtime, say, something like V8, Sprace Monkey, Spider Monkey, one of those monkeys, is smart enough to figure out that you don't need the variable anymore, and it's going to clear the variable out. But sometimes, even though you no longer need an object, the runtime still thinks that you do, and it's going to keep it around in memory. Now you're unintentionally using memory. Now this is normally not that big a problem, but if it happens inside a loop, or if you have a single page application, which is very long running, this can be a little dangerous, and that's going to be called a memory leak. Now let's talk about a quick snippet of code over here. You create an object. Let's say it's a big object, and you do something with that object. Now your runtime things is anyone using code, like is anyone using X after it gets out of the scope? No. So I'm going to get rid of it. On the other hand, if let's say that that object was being used inside of a callback function, the runtime things, okay, now the DOM event can fire at any time in the future. Now if I throw away X, this function is going to fail. So it's going to keep X inside the memory, and it's going to keep it around. Now if this is what you want, which in most cases it is, it's called, it's a normal behavior, but if it's something that you don't want, this would be what is known as a memory leak. So the big problem with memory leaks is that it's not like a compilation or a syntax error. It's not a problem with the input that there is. It's unwanted, but valid behavior. It's like saying my output is wrong. It's a flaw in your logic. So there is no tool that's available as of yet, which can detect and say, hey, you have a memory leak over here. But on the other hand, there are good tools available, especially in the JavaScript world lately, which help you detect your memory usage and identify it, but it's up to you to determine these things and be able to spot them. Now let's take a look at, so let's take a look at this quick example. I have a class called big object. I have an array and I'm going to push a thousand times a five byte string. I know that strings can take up more memory and there's a lot of things, but for the sake of simplicity, let's say that's five bytes. Now I have a small function called do something, which is just going to print hello and I'm just calling big object and I'm going to do something. Now when this is executed, pretty much no memory is used. The reason is that my array is being assigned, but it's not being used later. So the runtime clears it out. B1 is being used, but it's not being used later on. It's not held on to because of some DOM element or a callback. So it's cleared out. Now let's do something else. Let's put this do something inside and callback function. We know now that B1 can be used up at any time in the future, but still we're not using that much memory because the place that's actually gathering the memory, the five kilobytes of my array, now that is not used up inside the callback. The runtime is smart enough to determine that, hey listen, even though I don't need the whole object, I don't need this particular variable. So it's going to discard that. Now let's make a tiny change to this function right now and in this do something, I'm just going to use my array and I'm just going to use one item from my array over here. So this means that that whole five kilobyte array has to be pulled into scope over here and because this do something is inside a DOM, is inside a DOM call, the whole five kilobytes array is kept inside memory. Again, if this is what you want, fantastic. If this is what you don't want, that's a memory leak. Now what's interesting is that if you do have a callback and the same thing, let's say we did whatever we were doing before, we do use a callback, but then we remove the DOM node and then later on we check the memory again. We see that no memory is being used or very little memory is being used or whatever. The reason is that once the DOM node was cleared, even the callback was a reference from a DOM node. So you can think of it as even nodes are objects, even callbacks are objects kind of thing. You can think of it in your head. So if you remove the DOM node, the callback loses the reference and everything gets cleared. The key takeaways from whatever we discussed so far is that if there's a reference to an object, that object is in memory. If an object is being used inside a DOM event, that object is in memory. It's basically being pulled inside the closure by a process called querying. And if an object is on the global window, it's definitely going to be inside your memory until you remove it later. And the object can be removed only when all the references to this object from other places are removed. The important thing to realize is that when runtimes are incredibly smart at clearing out unneeded objects, the problem that happens is that so many times your code just works and you don't know about what's happening behind the scenes and sometimes objects can get stuck in memory without you even knowing that this is happening. And by the time this actually you realize that there's a problem over here, it's probably too late. So you need to be aware of the rules and keep in mind what kind of functionality is happening behind the scenes. So let's next talk about something called a retaining tree. Let's say I have an object called foo and I have two variables on this object foo. Now both of these are five kilobyte size. And when I have a DOM node and I'm going to attach to a click event, and I'm just going to use one of the arrays over here. You might think, OK, I'm just using one of the arrays. The runtime is smart enough to figure out which of the arrays was required before. So you might think that, OK, five kilobytes of memory is being used, which actually is using 10 kilobytes of memory. The reason for this is because foo.b1 is being pulled into scope over here, this means even foo is being pulled into scope. And because foo is pulled into scope, it has to keep both of them on the object. Since b2 has a reference, so this is what happens. So essentially the run time sees that, OK, there's a DOM node that's something that exists. So I should hold on to it. Now this has a click callback. The click callback requires one object over here. That is retaining the foo object, and the foo is object is retaining foo.b2. It's a little confusing, but think of it this way. Even if one of, if your object is like a tree, even if one of the items is being held on to from a memory, and your whole object is stored inside a callback, anyway, this will become a little bit more clear in the coming slides. The next thing we should talk about is that you can also possibly leak DOM nodes. Now let's say I have two links inside HTML. I've got a link ID of one and a link ID of two. Now I assign both of them. I use document.getElementById, and I get both of them, get references to both of the elements inside my JavaScript. And I add an event listener that when a click happens, it's going to remove the second DOM node. Now even your DOM node take up some, DOM nodes take up some memory. Now let's say that I open up my profile, or I see how much memory is being used. I see there's actually memory used for two nodes. Even the node that I cleared out, the memory has not been recovered for that yet. The reason for that is that even though in the UI it was removed, since there's still a reference to the variable two, and there's a reference to the variable two, it still is holding on to that DOM node as a conceptual entity because in JavaScript, things work like pointers. This is not passed by value. We're holding out a reference to that DOM node. It's called an orphan DOM node or a disconnected DOM tree. There are plenty of terminologies to describe this. But what will happen is that this will still be in memory. And this is called a DOM node leak. I don't know, I call it that. But the other thing you should keep in mind is that if I put the same variable two inside the callback, now no memory is going to be leaked. The reason for this is that the variable two, the moment it goes out of scope, the moment it goes out of scope, any references to that has been removed. So because of this, the moment the DOM node has been removed and a reference to it has gone out of scope, there is no more any references to it. The runtime can figure out and it can say I'm going to clear out this DOM node. So these are some tricky, subtle things, but you can play around with it yourself. And a good example is to probably put a debugger or put a console log to see what the values are and see if they still have references to it. So for example, if over here, if I actually put a console.log two, even after removing the node, I can still see a reference to the node. So these are ways that you can understand about how your runtime behaves yourself. Now, some simple tips about how to avoid memory leaks. I'm guessing that these are parallel to simple, but let's talk about them anyways. One of the most important things is try to avoid using anonymous functions for events. Now you may be really careful and you might use exactly what you want and prevent leaking stuff. Tomorrow a co-worker or an intern might come in and just shove all sorts of variables over there and pull everything into scope. Now that can be a little dangerous and that can be a little problematic as well later on. Instead of that, consider isolating your event handler functions, either in a separate object or a separate portion of your code and then handling it over there. Now a lot of tools like for example React and Angular and all these guys tend to encourage this or probably enforce this particular thing if you have used React and Flux and all of those kind of tools. So this is good that anonymous functions to handle callbacks are being discouraged. Another tip is pass only what you need. So for example, if I have this.user.identity.name and over here, as I see over here, I'm passing this.user as an object. Now if I only need the name, I don't need to pass even identity, I don't need to pass user because suddenly user has been pulled into scope, identity has been pulled into scope. And if I need to clear this out later on, if I need to recover the memory for this, I need to find the callback, I need to remove the callback, I need to remove all references for the callback. It might seem a little confusing but once you actually spend a little time thinking about this particular concept, it makes sense. You have to think about in terms of retaining trees. You have to think about what does the run time need for this function to execute and later on, how can I prevent it from getting what it gets? But the thumb rule is if you pass more specific values around, as a general, it's a good habit not just to callback functions but to other functions as well. If you try and instead of passing around big complex objects, pass around only the sections of the objects that these functions explicitly need. And this will help you in the long run make habits which avoid memory leaks happening on a regular basis. Another thing is to just generally use good judgment. Now one of the most important things you need to understand is that you can like premature optimization is a root of all evil or something like that. But what happens is that you can spend a lot of time worrying about the little things, I'm saving 2 kilobyte, I'm saving 200 bytes or something like that. But in the large scheme of things, it's not going to make that much of a difference, especially when a jQuery UI calendar can take up 150 kilobytes of memory. On the other hand, you need to learn how to be pragmatic. Because of the way it's structured, because of the way your third party tools are structured, you will have some unintentional memory usages, but it's okay. The important thing is to be, the important thing to things are, one is know when you're working with very large objects. So for example, if you're working with, you know, you're fetching a JSON data source of 10,000 data points and plotting them, you need to be a little careful with memory then, okay? And you need to learn how to profile your memory usage. And so for example, avoid big complex objects, pass only whatever variables you need and basically the same stuff. Now what I thought about was I was going to give you some screenshots and things about how to use DevTools. Instead of that, I'm going to do something slightly different, which I haven't planned this out, but this is my talk. It's a HTML page written with a tool called Remark. What I'm going to do is I'm going to try to find a memory leak in my talk itself. So I'm going to pull up my Chrome Inspector over here. So this is one of my favorite tricks for this. Now let's say that I have a situation where I have this page. Now if I go to 17 slide, come back to 15 slide, whatever memory was created should be removed. Now I have a suspicion that I'm leaking memory when I change slides. Now how do I justify that? How do I test that? Now what I can do is I'm going to load this up on a fresh pristine state or I come to the state where I want it to be. Now I'm going to, I have this thing called take a heap snapshot. I'm going to take a snapshot right here. So I'm using 5.3 megabytes of space. Now I'm going to go to slide number 18, come back to slide number 15. As you can see in this URL that's getting updated. Now I'm going to go back to my profiles and take another snapshot. Well, I actually have lost memory. I've gone from 4.5.3 to 4.8. That's after the guy who wrote Remark.js. So in fact, I can even say, so what's changed? So now let's look at this way. I can go through my section over here. So there are two parts that you need to be aware of over here. One is if you open up any object over here, usually you can find, this is something called your retaining tree. So for example, this is all minified code, so it's not going to make much sense. But let's say that this object 84479, which is probably the syntax highlighting. I mean if it has batch closure, coffee script, it's probably the syntax highlighting stuff. So this object, it's being held because of all of these anonymous functions. So this means that this object is being, if it had to be cleared out, it's being used up in all of these anonymous functions. And even over there, I can see where in what order the functions were being called. So essentially, as you see, it's winding its way down. So if you do find a leak, you might have 10 different places which is actually using up this one particular object. And for you to really clear it out when it's no longer required, you have to go to all 10 different places and you have to figure out where you have to clear them out. And that's why fixing memory leaks are a little problematic. Now another trick is, for example, you can go and you can say comparison. Now I can say I want to compare it with snapshot one. Now over here, I can see all of the, you know, for example, these are the strings. In fact, the strings were removed. There were quite a few strings like all of these strings which were removed then or these are new, yeah. These were new strings. These were deleted strings. So for example, these strings existed before, but now they don't when I changed my slides from back and forth. And I can even see which with the newer ones which objects are holding on to it. And sometimes it's not very helpful. Sometimes it is results may vary. That's all I can say. But learn how to use these things well and learn how to do these things on a regular basis. Another thing you can do is I can sort of record heap allocations right away. And I can keep changing my pages and I can see how these things change and I can go back and I can find out all sorts of stuff. One very important thing is look for something called a detached DOM3. This is a very useful tip that I've even seen memory leaks in some of the Google applications. This detached DOM tree is basically DOM nodes which don't have parents, which are not on the tree, but still the DOM nodes exist. They're just zombie DOM nodes lying around. So you can find them out. So I can see over here, there's a HTML div element. I don't know if it's visible, but there's a HTML div element that's somewhere from, you know, it's probably leaking from the convert markdown function. So if I was the author, I'd figure out, okay, fine, there's a div that's been created, that's not being used from the convert markdown function. There's also a timeline which allows you to, I don't know why it's not letting me see it, but you can see your memory go up and down and you can see a graph. So you can see when there's a spike and you can see there's probably a memory leak. The thumb rule is try as much as possible to find, like, you know, learn as much of DevTools as possible because that's really gonna set apart. Yeah, so let me just quickly use this. I have a slide, let me just clear this, give me a second. So I have slide number 18. I can go to, say, slide number 11, come back to slide number 18 and click finish. I can actually see how my memory grew and this is where, for example, the garbage collection event did take place. So as you can see, the garbage collection is happens every few seconds or happens as your memory grows. So once your memory got too much, it drops. Similarly, you can see your JS heap getting down and you can see a number of DOM nodes. So the fantastic thing about this slideshow is, as you can see, the number of DOM nodes increase or decrease, but when I come back to the same place, the number of DOM nodes, two, two, six is exactly the same. That means not even one extra DOM node was leaked when I changed my slides. So these are ways that you can use your apps. These are, you can test your apps, you can test your single page apps and hopefully it can make far more responsive and enjoyable to use web applications. So that's pretty much it. I'll just skip all of these slides. You can see my slides at bit.ly slash js4 underscore memory. Hey, Remark.js is really remarkable in terms of memory. What I would like to ask is, do you suggest some automation tools for lazy people who are like, I don't want to go to the dev tool and record it myself and have a look? Is there any tool that could go and give me, say for example, all the zombie doms or the dangling? So that's a pretty nice question. Now, I've been spending a lot of time trying to find something that does this. So the problem is that any automated tool does not expose, I've looked into phantom.js, maybe phantom.js or something like that which can push these information out. But as far as I know, no testing or CI tools put this information available. Now, they have started doing some things, like for example, like there is a new object available called window.performance. So if you go to window.performance.memory, you can see some of the information about the memory, but I don't know why they're not using the heap at all, but maybe as Chrome or some browser vendor exposes more information about these things, that could help. Okay, cool. Thanks. Thank you, Arindam.