I have some code that is working, however it has a memory leak in it.
What are some good strategies for tracking memory leaks in node.js?
What steps should I follow when looking for such leaks?
How can I track the leak in my code?
Thanks
You can figure this out by profiling the memory usage of your application.
Javascript objects are allocated on the heap, so you'll want a tool that can dump the heap. After acquiring a heap dump you can inspect it and see how many instance of a given object (or function) exist.
E.g., for your code you know you create a socket whenever a user connects. Dumping the heap while three users are connected should show ~3 sockets. Dumping the heap after those users disconnect should show ~0 sockets.
You can actually use the Chrome heap dump analyzer with Node.js heap dumps.
Documentation on the Chrome heap dump analyzer: https://developers.google.com/chrome-developer-tools/docs/heap-profiling
Project that allows you to take Node.js heap dumps and inspect them in chrome: https://github.com/bnoordhuis/node-heapdump
Just fyi, functions are going to show up in the heap dump under the (closure) section.
You'll want to make sure you name your functions (even if they don't need a name) so they show up as something useful in the heap dump.
For example, something like
function() {
}
will just show up as function() in the heap dump. Where as:
function taggedFunction() {
}
will show up as function taggedFunction() in the heap dump. If you create 100 taggedFunctions then you'll see taggeFunction in the heap dump 100 times. Basically, naming your functions lets you figure out if you keep creating and leaking them.
Related
I'm making a rather extensive game using Javascript. It is a kind of online game maker that allows players to upload media files and use them to create worlds. Unfortunately, it is rather prone to crashing the browser tab at unpredictable moments. So far, I have found no pattern to this - sometimes it happens within a few minutes, other times it can run for hours without a problem.
I have tried enabling logging in Chrome, but the crashes don't seem to generate an error report in the chrome_debug file.
I thought it might be that the program was using too much memory (given the game's open-ended nature, some worlds can involve downloading rather large data files - though this seems unrelated to when the crash actually happens - while large worlds do seem to be more crash-prone, they do not always crash when the world's data is loaded).
I tried using Electron to turn it into an executable app, but the app still crashes. That shouldn't happen if it's a memory issue, right?
Is there any way of finding out what is causing the code to crash?
Most unpredictable crashes in Javascript are caused by memory leaks - objects that are still stored in memory and not being picked up by the garbage collector. Every object in Javascript is stored in a variable somewhere within the global scope, or is associated with another object that is itself connected to the global scope. When a "branch" of the "tree" is removed and can no longer be accessed by the global scope, the garbage collector destroys it.
However, if an object is not being removed from the global scope when it should be, it remains in memory. This usually happens when objects are added to an array but are not removed from that array when they are no longer in use. Over time, these objects build up until the process crashes due to memory overload.
To find memory leaks in Chrome, press F12 and open the Performance tab. By recording the page over time, you can view the amount of memory being used. The green line (nodes) is the most important here - it refers to the number of objects in memory. If nodes are constantly increasing over time (there will always be increases and decreases, but if the overall level is constantly rising) this generally means there's a memory leak.
To find which specific objects are causing the problem, open the Memory tab to take snapshots or timeline profiles of the memory heap. This gives you a count of the specific objects that are in memory at any given time. If there are more of some kind of object than there should be, that's where the leak is.
I have a problem about memory management.
My simpliest code is here:
var url="/abrapo.php";
var ob={start_:100, token:null}
function post_token(){
$.post(url,{access:ob.token})
.done(function(data){
console.log(data);
ob=data;
});
}
I call function post_token every seconds. So after 2000 call user has problem of memory, ram goes up to 2GB. I don't need to save anything just want to log data after post and clear memory. I've already googled and find delete ob. But it does not clean the memory. What increase memory and how can I clean it without reloading the page
Use your browser's profiling tools to determine where you're accumulating memory. In Chrome these profiling tools are located under the Performance tab in the Chrome Developer Tools F12.
Click the Memory checkbox near the top to enable memory profiling
Click Start Profiling and Reload Page (Ctrl+Shift+E)
Let the profiling run for a while, most pages load in 2-3 seconds but it sounds like your page needs to run longer than that
Click the Stop button to halt the profiling
Among all the other performance graphs, you should see one for memory usage that looks something like this.
You can use this to see if, and when, the browser is performing garbage collections on the Javascript heap. You may need to manually clear certain objects by setting them to null. Also, try to avoid cyclical references and other complex referencing patterns that could cause the javascript engine to hold on to objects longer than it has to.
Click here, for more about the memory management and garbage collection in the browser.
I had similar problems while writing UI for a data acquisition device and managed to make it fly by setting every variable containing large data arrays to null whenever not used.
Your use case isn't easy to replicate with just your code, but I suggest you try setting
data = null;
and
ob = null;
whenever not in use.
You might have to tweak suggestion a bit, say by assigning only token:
ob.token = data.token;
in such case only token would have to be set to null
ob.token = null;
What this achieves essentially is that it gives garbage collector a chance to clear unused objects since variables using those were clearly set to null. Oh, yes, and memory profiling is your friend to find out what exactly should you null
According to your code example, the problem is with console.log(data)
it make your object accessible from Console. The Garbage collection will free memory only when the object is no more accessible.
I have a large app thata I am debugging. I have noticed a saw-tooth memory pattern that indicates that there is frequent GC going on.
In an effort to debug this I am trying to find the contents of the memory that is being GC'd. Is this possible in chrome with dev tools? I know I can take heap snapshots, but how do I guarantee that this happens immediately before and after a GC? I know I can trigger a heap snapshot from code, but same question.
Insight into the garbage collection is not available yet in the DevTools. I have requested this feature some time ago though. You can "star it" to indicate that you would also like to have it.
As for the snapshots, you won't be able to use them for your purpose. Before each snapshot is made all garbage is collected.
Are "dead" (unreachable) objects included in snapshots?
No. Only reachable objects are included in snapshots. Also, taking a snapshot always starts with doing a GC.
source
Your best shot is to record heap allocations ("Profiles" > "Record Heap Allocations") and use memory snapshots to understand what objects are being created by the app. With that knowledge, you can try identifying shortly lived objects (that cause the sawtooth pattern).
BTW, if you are using requestAnimationFrame, you should know that it's causing saw tooth pattern by itself.
With Record Heap Allocation profile type you can get the information about allocated objects.
You need to enable "Record heap allocation stack traces" option in the DevTools settings.
See screenshot.
After that you need to record "Record heap allocations" snapshot type.
The recording process may significantly slow down the page because DevTools scans the js stack each time when the page allocates an object. As a result you will get the snapshot which has the information about allocations. In many cases DevTools can detect the class name of the objects. See screenshot.
In the snapshot you need to select Allocation view.
I think the information in the grid could help you to solve your problem.
In the screenshot you can see that there were 41k allocations for a class but only 12k of them still alive. So 29k objects were the garbage. And even if you don't see the name of the object you could jump into sources where the objects were allocated.
I have a single-page app that is leaking fairly substantially. I am trying to track down the memory leaks using Chrome's built-in memory profiling tools. The heap snapshot has been giving me a lot of success in tracking down quite a few problematic code blocks, but I have now reached a bit of a dead-end.
I have taken a heap snapshot and isolated a variable that has clearly leaked. I then open it up the retainers view so that I can see why the object has not been garbage collected. What I am now seeing in the retainers view (see below) is confusing me. It keeps reaching a dead-end even though it claims that the given node in the graph still has a distance of 11. I'm not sure why it won't let me dig into the object when it says that there is still depth there. I was expecting that I would be able to expand all the way to a global variable on the window object.
Is there any kind of assertion that I can make to verify that a particular object can be GC'ed in Javascript? The purpose is to have a unit test that asserts a memory leak is fixed.
at this point I don't know of any direct language support for this - I don't think Javascript has weak references or finalizers, which is how I probably would have done this in Java or C#.
You cannot have any javascript code that detects if a specific object can be GCed. The very code that would test it would keep it from being garbage collected because that code would, by definition, have a reference to it and the garbage collector will not GC something that still has a live reference to it.
The things you can do to verify that there is no memory leak:
Devise a test that runs the offending code over and over and measure the total memory usage of the browser to verify that the memory usage it not going up and up and up.
Assign a gigantic property value to the object (e.g. a mongo string) that is so large that you can clearly see if these objects are leaking in total memory usage.
Use various developer tools (which vary by browser) to look at the browser memory usage in finer detail.