SummaryRecently we were executing a memory usage analysis in my current (node.js) project. This article summarizes some of our findings, which may be useful to other projects. It does not describes the very basics of the mark-and-sweep garbage collection algorithm. Instead, it focuses on the details of the particular tools we used.
A script in this document simply creates an instance of an object, using constructor function and assigns it to global scope. If you click on “Action” and then “Set and clear” button to force browser do its initial compilation work, then record first heap snapshot, then click on “Action” button and then record second heap snapshot, you could see something similar to the picture below. Just select the second snapshot in the left menu, then select “Comparison” view and then select the first snapshot as comparison target in the dropdown, next to class filter input box.
|Chrome developer tools / Profiles tab|
Upper table shows the difference between two snapshots. All objects (either new or deleted in the second snapshot) are grouped by constructor function name (just as in Summary view).
First column (“Constructor”), is a tree view. On the first level you can see constructor function name (object instance grouping parameter). On the second level, you can see instances in the selected group (each instance has a unique id with “@” prefix). On the third level, you can see properties of the instances, then, on the lower level – properties of the corresponding objects and so on.
Further columns in the upper table describe difference in the number of instances and total size of each group (on the first level). On the second level, you can see whether a particular instance is new or has been deleted between the compared snapshots.
There are a lot of articles, which describe how you can attach a debugger to a new or running node.js process and then either debug or record heap snapshots. What is slightly less known, is that you can actually programmatically record heap snapshots without the need to attach a debugger. That is very easy to do using “heapdump” NPM module (https://github.com/bnoordhuis/node-heapdump).
For example, you can simply create a new route, which can be called any time and will create a new heap snapshot file on disk. It can even be used in production (if you closed it from unauthorized access, of course):
Using this heap dumping technique, we have very easily found that many of our processes store big unused “geoip” data files in RAM, since corresponding library loads them into memory non-lazily. Simply removing these files, greatly reduced memory consumption of our application.