Can I get the GC'd memory from dev tools? - javascript

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.

Related

How to find out what's causing my Javascript to crash the browser tab?

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.

Using Chrome's heap snapshot analyzer, how do I interpret dead-ends in the retainers view

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 a way to control Chrome GC?

I am working with quite large volume of data.
Mechanism:
JavaScript is reading WebSQL database, then assembles data into Object that has tree structure.
Then applies to tree object knockout.js (makes elements observable) then data-binds
and then applies Jquery Mobile UI at the end.
Whole process takes unacceptable amount of time.
I have already optimized algorithm that makes tree object out of data,
also optimised conversion to observables mechanism by pushing items directly into ko.observable arrays and calling hasMutated only once.
I am applying knockout.js IF bindings to not process invisible tree nodes in UI until parent is opened.
Performance here is key.
After inspecting page load in timeline in Chrome developer tools I have noticed that Garbage Collector is doing cleans on every concurrent call when I am building tree object.
Question: Is there a way to temporarily disable Chrome GC and then enable it again after I am done with page processing?
P.S I know I could add reference to part that gets collected, basically introduce object that dominates and prevents GC collection, but this would require substantial changes through the code, and I am not sure I could keep it long enough, and it is likely to introduce memory leak. Surely there must be better way
No, there is no way to disable the garbage collector. There cannot be, because what is Chrome supposed to do when more memory is requested but none is available?
(Also, the garbage collector is very fine-grained and complicated; your screenshot is a bit too small to be readable, but in all likelihood what you're seeing are small steps of incremental work to keep up with allocations, and/or "minor GC" cycles that only operate on the relatively small area of the heap where new allocations happen.)
If you want to reduce time spent in GC, then the primary way how to achieve that is to allocate fewer and/or smaller objects. Yes, that can mean changing your application's design so that objects are reused instead of being short-lived, or similar changes in strategy.
If you allocate a lot, you will see a lot of GC activity, there is just no way around that. This is true even in languages/runtimes that are not considered "garbage collected", e.g. in C/C++ using new/delete a lot also has a performance cost.

Detect node.js/javascript memory leak in code

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.

Tool to track down JavaScript memory leak

I have a web application which has a memory leak somewhere and I am unable to detect it. I already tried the Chrome developer tools which normally works great, but I am unable to track down the lines of code which are responsible. The Chrome tools just give me too much information and I can't relate the objects in memory to my code.
Are there any other tools that might be helpful?
update:
Lets use Record Heap Allocations profile type.
open devtools profiler
do a warm-up action
start profiler
repeat action a few times
if the action has a leak you will see the same number of groups of blue bars in the overview pane
stop the profiler
select one group of these blue bars in the overview
look into the list of objects
See screencast Javascript Memory Leak detection (Chrome DevTools)
was:
You can use the next scenario for fining memory leaks.
open devtools profiler
do an action that makes a leak
take a heap snapshot
repeat steps 2 and 3 tree times
select the latest heap snapshot
change filter "All Object" to "Objects between Snapshot 1 and 2"
After that you will see objects a set of leaked objects.
You can select an object and look at the list of retainers in Object's retaining tree
Use the innerHTML and outerHTML values of the element in the Detached DOM tree view of the Heap Profiler to map objects in memory to your code and track down memory leaks.
jQuery ajax requests were the biggest culprit in my app. Locate all your ajax jQuery functions: .ajax(), .get(), .post() and content setters: .html(), .text().
Go to the network tab in dev tools, refresh the current page 10 to 20 times. If you see things stacking up too frequently, or calls not being completed, you have a memory leak.
Here is a recent memory leak I was able to solve with jQuery.load()...
if(!jQuery.terms_html)
$('#tc_container').load(STATIC_DOMAIN + '/terms.html', function() { jQuery.terms_html = $('#tc_container').html() })
else
$('#tc_container').html(jQuery.terms_html)
Also, the latest version of jQuery at time of writing this is 3.3.1. Having the latest version installed is the best way to get started, if possible.
https://github.com/jquery/jquery/releases

Categories

Resources