Please note that as of Aug 3, 2015, StrongOps has been EOL’d. Check out StrongLoop Arc for the same capabilities and more.
In last week’s performance tip, we discussed in detail how to leverage Google V8’s heap profiler to diagnose problems with Node applications. In this go around we look at different leak patterns and how a good diagnosis can lead us to find the root cause of a potentially troublesome production problem.
Rapid memory leaks are easy to identify and often the cause of many memory issues. Node by itself is very sensitive to errors and exceptions and will crash due to out of memory exceptions. Slow leaks are the most difficult to find and often require profiling over long periods of time to properly identify.
Slow memory leak pattern
Rapid memory leak pattern
Profiling by itself provides isolation up to type and count of objects in the heap and in retainers. We provide that in StrongLoop Arc; however to get down to the line of code, you need deeper inspection.
Client Side Heapdumps : Chrome Dev Tools
Server Side Heap Snapshots: Triggered, Timed, Thresholded
Server side heap snapshots are needed during analysis in higher environments like performance testing, UAT or production. These snapshots can be collected using the Node heapdump module written by StrongLoop founder, Ben Noordhuis.
npm install heapdump
This module helps gather server side heap dumps under production load using 3 techniques – User issued SIG commands, Timer based programmatic and Memory Threshold based programmatic. More details available on this Node Heap Snapshots blog.
Let’s conduct a mock exercise by forcing a memory leak. Include the heapdump module into a leaky class called ChocolateClass that simply adds 100 units of objects every second into an array – sugar.
Running this application and taking heap-snapshots using the Kill -USR2 <pid> commands gives us two heapdumps to inspect side by side.
Now we can load these into Chrome Dev Tools for visual inspection.
We sorted the first heap snapshot by object count and found that the ChocolateClass was the top memory utilizer with 37% of the objects in heap. But this is not enough evidence to conclusively prove anything. We can see some retainers at higher levels for other types of objects too.
Inspecting the second heap snapshot taken on the server after a delay of 1 minute from the first one, confirmed our suspicions. We can see that the ChocolateClass has suddenly bloated in heap consumption to about 77% of the heap size. The shallow and retainer sizes of this class is now close to 30% of overall.
Drilling down into the ChocolateClass, we see it’s the sugar array which is causing all this bloating. We can even inspect the call path, the data elements and attributes and all the objects in depth. Retaining paths are actually any paths that link objects with GC roots. Path inspection is critical here.
Interestingly, we can see that there are nearly 47K sugar units in the array and the array is not being garbage collected properly.
Understanding some basic memory constructs in Node.js
StrongLoop Arc is a graphical UI for the StrongLoop API Platform, which includes LoopBack, that complements the slc command line tools for developing APIs quickly and getting them connected to data. Arc also includes tools for building, profiling and monitoring Node apps. It takes just a few simple steps to get started!