 All right, we'll start off for the ones who haven't come in. I didn't scream at them loud enough. Feel free to do it on my behalf. Let's settle down. Pleasure to introduce Jaydeep Singh from ThoughtWorks. Big round of applause for him, guys. Jaydeep is a front-end developer and a UX engineer at ThoughtWorks. ThoughtWorks guys are everywhere today, aren't they? It's pretty cool. He likes to experiment with different JavaScript design patterns and cross-bowser implementations. Throughout his career, he's worked on many client-side apps and frameworks like Backbone, Angular. He's been speaking at different forums about front-end practices and workflows and believes that jumping to any framework without an understanding of the core usually leads to code, which is less optimum and harder to debug. Thank you. Thank you. That was for me. Jaydeep's here to talk about memory profiling your applications. Very core thing right now. Everybody talks about how JavaScript could be bad performance-wise and all, but it turns out that usually happens with bad code. And there are a bunch of tooling and tips to make your application smooth, performant. And Jaydeep is going to give us the load on that without further ado, Jaydeep, all yours. All right. So how many guys have been doing memory profiling before? Quite a number. So the basic motivation for this session is I have been working on a lot of front-end applications, which are mostly single-page apps. And we have been having some problems related to performance, where we have seen the applications become slower as they have, as the user spends more and more time interacting with the application. So I started looking into the tools we have. Mostly I have been working with the Chrome Profiler. And I'll be sharing something on that. So this is a screenshot of the Chrome Profiler, which actually shows you how the memory used by the events and the DOMs and the DOM nodes increases is increasing for a specific application. I'll talk about it in a bit. So this is how it looks. Basically, this is this portion. Sorry. You can't see. So this is a screenshot. Yeah. So what I was saying was these basically are the leaks which are happening whenever you do any interactions. So this is what we should be looking at. And this is what we should aim to prevent. So JavaScript engines, every browser has a specific JavaScript engine. These are some of the popular browsers and the names of their JavaScript engines. I've mostly been working with Chrome. And I think if you are concerned about the memory and performance of your application, you should try to look at the way the JavaScript engines work. So we are going to talk about V8, which is Chrome's JavaScript engine. The components which it has is these are some of the components. And I'll just briefly take you through. The base compiler basically passes your JavaScript code and generates native machine code, which is actually very fast. And the object model is slightly a bit different from your general JavaScript model JavaScript. Usually stores objects as associative arrays, but V8 stores objects as hidden classes, which makes it makes them very optimized for quick lookup. So it actually stores them as classes. Then there is a runtime profiler which actually keeps checking your code during the execution and keeps a note of the functions which are taking the most time for execution. So those functions basically are called the hot functions. You have an optimizing compiler which actually tries to optimize all the hot functions by reducing the calls and inlining those functions. Then there is the optimization which keeps happening continuously at any point of time if the compiler decides to ignore the optimization or if it thinks the optimizing compiler has made any assumptions which it doesn't seem right. It actually ignores those optimizations and the general execution continues. Then we have the garbage collector. I think most of you would be aware of what it is. So what garbage collection in JavaScript it basically is a process where the compiler decides to, sorry, the garbage collector decides to free the memory which was being used by the objects. As soon as any all the references to those objects are removed, the memory is being freed. But again, unlike other languages, it is not really possible to forcefully free the memory. So we are going to look at some of the traps which we should try to avoid. Now what we generally tend to be doing is we generally try to assign any objects which were being used in the hope that they will eventually get garbage collected. But all of our assumptions are not always correct. So these are some of the things which I think are common mist conceptions. We have delete. So there is an object which has a key and we try to delete the key x. And we think that this will free some memory. So here it is important to note that this is actually trying to modify the structure of the object. And it will not be garbage collected until all the references to that object have been removed. So this delete function is delete is not actually doing any good here. And on a side note, we should always try to make as less modifications to the structure of an object. Because as I told you, the v8 engine is v8 engine stores objects as classes. So any changes you make to the structure of an object will make it, it will have to remake those classes. So we should try to not change the object structure as much as we can. Now we have null. What we usually do is we think, OK, this object is not needed anymore. We can assign null to it. But again, if that object is being used by any other, if that object is being referenced to any other variable, it will never be garbage collected unless even if we assign it null, it will just keep it in the memory as null. Then you have global variables. How many of you like global variables? I like that. So global objects, I think we all know that the global objects will never be garbage collected until the page refreshes or we navigate to a different page. So that is something we should keep in mind that we should always try to enclose the variables inside functions so that they can be garbage collected as soon as the function execution ends. So we should try to minimize the use of global variables. So this is a general rule of life which applies to JavaScript as well. So basically three things, if you do these three things, well you will, I cannot assure. But most likely you will not run into any memory problems. First of it, first is the scoping of the variables. As I told you, try not to keep any global variables. And unbinding event listeners, a lot of times we do a lot of DOM manipulations. We try to modify the DOM. We try to append new elements, remove children. But we generally don't remove the bindings or we tend to miss it sometimes, which actually leads to the event memory increasing, as we saw in the screenshot earlier. So that I think is an important thing to do. Cleaning cache, what that means is we try to cache some variables sometimes. So sometimes we have some data requests where we try to get some variables from the server. And we try to cache that data inside our application so that we would want to reuse that data. But we need to be consciously looking or we need to have a mechanism where we try to ensure that any of the objects which are no longer being used, they are cleaned. So these are the common things where we can easily spot some leaks happening. I'll show you some examples. So this is a function which we have fly. It has a new object. We create a new object of the type my object and we make a method call. So in general cases, whenever this method fly executes, this call will go. And as soon as it ends, it will just garbage collect the object obj because it is no longer being referenced or being used. We try to contrast it with this minor modification where we are returning the object obj. And there we are assigning fly to insect. So insect is actually holding the reference to obj. So even if the function execution ends, this will definitely cause a memory leak. So we should try to avoid such things. Or if we are doing it on purpose, we should make sure that the objects are dereferenced when we don't need them. Then we have closures. So in closures, we tend to return functions within functions and because we can have context specific variables. But again, an important thing to note here is whenever we are having objects, we should try to not return any references to the objects because as you see in the above code, since it has the reference to the large string, it will hold that reference for forever. So it will not be garbage collected. So this is just a small change where we are not returning the object. So the lower one will not have any leaks. Timers, who likes timers? No one? It's all or two people who use timers. So again, a very common mistake to make with timers is we actually try to, whenever we try to loop or do any kind of recursion using set time out or set time interval, we actually need to be very careful with the memory implications. So this code basically has an object which has an announcement method. And here we are calling the announcement within set time out recursively. So I'll try to run this code and one second. So this is your object and looks good. I try to call the announcement method. And I see that after every second, it is actually logging the statement. Now the problem here is, if I try to set the reference to this object to null, this will not stop. So essentially, the problem which we have here is, so see, this is still running, even if we try to assign null. So the problem here is, we have the reference to this. When we are doing this, we have the reference to my object inside this function. And this function is required for execution of timer. So since this function has a reference to my object, this will never let it to be garbage collected. So this is another trap which we should try to avoid. Now we come to the profiling part. I'll do a quick demo. So this is a simple application which has some blog posts from a list apart. And what it does is, these are the titles whenever you click on it, you see a summary of the post and you have a button which can do some action to the post. So it will just mark it as start or something. So you can navigate through them and you can do this. So now what we are going to do is, there is a panel called Timeline inside the Chrome, which actually traces your memory footprint as you use your application. So what I'm going to do is, I'm going to press this record button on the here. And what I'm going to do is click on couple of items, and I'm going to stop it. And here we have, so this is a problem with the code which we have, the event listeners. So this star button, if you see, it is actually doing something. So it has some event attached to it. The problem here is whenever you attach any, whenever you click somewhere, it is attaching a new event to the button of the specific post, but it is not really, not really clearing the earlier, the binding to the earlier post. So that is why the event bindings are increasing. And this is actually going to cause a memory leak. So what I'll just show you the code. So this part is responsible for creating that navigation from the data. And this is the portion which, this is the code which executes when you click on any of the items. So this is the part which has the problem. So this actually is adding an event listener to the click action. But again, when we try to click on any of the navigation items, it is not really clearing the, it is not really clearing the bindings which were earlier attached. So I'll just quickly clear them and just show you how it changes the results. So first of all, what we are trying, what we are going to do is, we are going to create a new function, which is a clear post or something. The name should be something else. Mark a start and then we are going to move this code. Now we are going to just say, mark a start. So this makes it a bit cleaner. Also it will be helpful when we try to dereference. And then we again create a function which is clear bindings. So what we are going to do is just, instead of add event listener, we are just going to say remove event listener. And rest of the parameters are same. So here before we, whenever we click on any of the new items, we just say current item dot clear bindings. So now we'll try to do the same thing again. Then there is some error. So initially we don't have any item selected. So we are just checking if there is any existing item, only then clear the bindings. So here we go again. So here if we see whenever you click on the first post, some bindings are set up. And after that throughout the application, whenever you try to navigate to different items, we don't have any extra event listeners. So that is something to keep in mind. So another thing I wanted to show is the memory snapshots. Memory snapshots also help you to identify the possible problem areas or the possible objects which are actually causing a leak. So how you do this? I have an application which is fairly simple. What it does is it actually has an object and we create a lot of objects and we try to assign some of the references to a global variable. So just to see how it looks. So how we generally do the snapshotting is we go to profiles panel, clear all the existing snapshots, take each snapshot, take a snapshot and it will show you a list of the objects which it has in memory. Then I have a function which will create a lot of objects and leave some references intentionally. And then you have another snapshot. So what you do is you choose the comparison view and you actually can see that the item object which was there. So this is the item object which we created. So if we see there were 11,000 new objects of type item created and only 10,000 were deleted. So 1,000 are still in memory. So we need to make sure that whenever we are doing any actions we don't leave any such objects in the memory because in the course of the time it will have some memory footprint. So the next thing which I wanted to show you was the DOM leaks. So what are DOM leaks? Whenever you have some kind of DOM manipulation happening you try to append or remove a div. You need to make sure that whatever the children nodes are they are also removed whenever a parent node is removed. Because it turns out that the way JavaScript works if you just remove the parent node the child nodes are still hanging in memory and again they lead to something called DOM leaks which we are going to see here. So what we are essentially doing here is we are just creating. So we have this page and we have an empty div called P and what we are going to do is append a new div inside it and then remove it. Once we have removed it, removed it we are trying to add more elements to the div which is already being removed from the DOM. So again we go here. Same profiles panel we choose to take heaps snapshot has a list of items. Now there is slight difference here. So you say cause DOM leaks and then you take another snapshot which is you can see it is significantly bigger in size as well. So what has caused the problem here is you can choose a containment view and you can see a detached DOM trees. So here you can see there are 27 elements which are still hanging in memory even when they are not a part of any of your HTML. So that is something which is again which again needs to be taken care of that whenever you are removing any DOM elements make sure that you explicitly remove their children as well. I think that would be it. Any questions? Is there any easy way or tip to force garbage collection like in node we can just require the dashboard collected module and then force a garbage collection? Is it really possible to force a garbage collection? No, I don't think so it is possible. You just need to be careful about any of the references to objects which you are keeping. I think that should really not cause any problem. If you try to be a little careful about that that you are not using too many global variables and you are not assigning objects to any of the global variables. But would it be useful if there is a way to force garbage collection? Do you think so because at the end of the execution I could just say collect the garbage? Yeah, but the problem is it doesn't, the JavaScript engine doesn't know if you really need that object or not because you only assigned it to a global variable in the first place. So I think that is why it still keeps it in memory. Okay, yeah, thank you. In one of the slides early on you had mentioned that setting an object to null doesn't really give you any benefit from a garbage collection perspective. Could you just explain? So I always thought that setting it null is a good thing. Sorry? Always thought that setting null is a good thing? So null is a good thing when you actually, I'll show, just show you a slide. So here, if you are, so here what we are doing is in the code which is there. So what you are doing here is you are assigning a fly to insect. So insect will have this object called OBJ. So in such cases, unless you nullify the reference to fly, it will not get garbage collected because insect will still hold a reference to the OBJ. So in such cases, if you assign null to insect it is a good thing. But what I meant to say was if you try to, if there is an object and you try to assign null to that same object in the hope that the same object will be garbage collected, it might not be because it might have been assigned to any other global variable as well. I have a question. Hey, let's say we have a DOM elements which has been, we have an object which has been dereferenced from. Can you be a little louder? Let's say we have an object which is dereferenced from DOM. And it's not properly garbage collected because of its child objects. Okay. So it's pointed out in profiler. So how would we find out the reference of that object in the source code? Is it possible? So I don't think you can get specifics of which object it was in the source code. But obviously you can try to rerun your application and see wherever you do the DOM manipulation you can be a little more cautious. But it doesn't really tell you which specific elements are there. I have a question for you. Yes. You said the leakage about the DOM nodes. Yes, yes. So if a parent node does not have a reference but its child has a reference, then that means that the child is still there in the memory, though the parent has been removed from the, is being garbage collected. So I'm sorry, I didn't get your question. So you, as you said, if the parent has not any, is not having any reference being held by any other references, but its children has been. So what I was trying to explain was, if we try to append an element to the DOM which has a lot of child elements and then we directly remove the parent element, the child elements. Still possess no memory. Yes. It has been, that means that it is a memory leak. Yes, yes. Can we get a kind of references to that particular node, DOM element node, so that we can find that the particular reference is being pointing to that node. So that is the real problem. You can't really know whose children are these. So we, so if I try, if I try to run the garbage collector and once again relaunch the app, then, so you know, there's still possible in I, you can run the GC, in the production only, you can run the GC function and the GC runs. And in fact, in the Chrome, there's a flag. By launching the Chrome, you can run a flag, minus minus flags is equal to expose GC, there's a flag. So when you run this flag, when you run the Chrome along with this flag, you can invoke the window.gc function and it does always, the garbage collector always executes when you write this statement. So if there, if I have a scenario where I think that this particular DOM nodes are leaking and thereafter I just run the garbage collector and again, if we go through the same process, does this make help to me to exactly pointing out which DOM nodes are leaking and which are their parents or which are their parents. I think it might be helpful in those scenarios, but I think the problem again, the problem here is the JavaScript still thinks that you might need those nodes sometime in your application. So it is still keeping those references there, even if, even though it should not. But I think that should help. Hello. Hello. I have one question. Hi. Hello. Here, here. Oh, sorry. Yeah. So you're telling that the child nodes are still retained if the parent node is being removed from the DOM, right? Right. So do you have any idea why VA engine's doing that? It shouldn't be doing that, right? Sorry? Why is the VA engine doing that in first place? Oh, whatever the... Yeah, so what I said was I think it is retaining those because it thinks that the parent might appear again from somewhere. We don't have a reference to the parent, right? So it's useless to possess the child. So it's a bug in VA engine. I feel like you're retaining the things. So why, it should be a bug, right? Yeah, it should. We should be reporting that. We can try. I'm not sure though. Hi. This is regarding one of the question thing you said about closures, right? You said following closure pattern is not good because it's... No, no, I didn't say closure pattern is not good, but I just meant that you should be very careful when you are using objects and using them inside closures. See, if you're using a promise-based pattern where you want to do asynchronously, so you have very little options other than the promise-based model closure thing using. So is there any patterns that you can suggest when we are using with promised and the closure patterns? So I think if you try to do something where you are not really... So whenever you do closures, you actually try to... So I'll show you that same example which I was looking at. So this one, now this is also kind of a closure where you actually have the reference to this which is required inside this function. So I think this is a pattern you should not... You should try not to follow. I understand that what I'm saying is, let's say you have asynchronous module that you want to talk to. Correct. The way you can achieve is through promise. Whenever you can create a different object and when it returns. So at that point of time, you might need to have a reference to what all the objects that you have defined earlier, right? At that point, you obviously need the closure which can refer to those things. So you have no other way to access them. Yeah, I don't think in that way you have any specific... Because that is a very specific problem. I don't think you'll have any better solution for that problem. Hi, again regarding the DOM nodes. So I heard you say that only when the DOM nodes are appended to the page, only then and after that removed, only then will the reference be there. So is it because that we are adding them on the fly? That is why the reference is there? Or if the DOM element already exists on the page and still we remove the parent, the reference will exist? No, I think it is when you explicitly add them via JavaScript. Okay, so if we remove the references to the child nodes itself which we initially added, then will that solve the problem? Yes, yes, yes. Okay, have you... Guys, round of applause for Jaydeep. I'd like to take this opportunity to thank ThoughtWorks for bringing them down. It's been great having you guys here. Cheers, man. Thank you. A couple of... Oh, thank you, yes. ThoughtWorks. I shall think of you when I do my next Selenium test.