Tuesday, 1 March 2022
How to Profile a Memory Leak
Profiling memory leaks in Node.js
Node has a built-in profiler that can be used to profile memory leaks. Here's how to use it:
First, run your application with the following flags:
node --expose-gc --inspect=9222 app.js
This will start the debugger and open an web socket on port 9222, it'll also expose the garbage collector to us. Once the application has started, using chrome visit
chrome://inspect and click on "Inspect" under "Remote Target", this is the debugger running on the web socket.
Chrome should have now opened developer tools and allows you to take profiles and snapshots. For a memory leak specifically you'll want to take a heap snapshot. This can be done by navigating to the Memory tab and clicking on the "Take Snapshot" button.
The first snapshot will be a full snapshot of the heap. This is the snapshot that you'll want to compare against.
Use the application as intended either manually or under test and take a second snapshot by clicking on the record icon in the top left corner.
This will give you a second snapshots so you can compare the differences between the too. To do this filter the objects by selecting "Objects allocated between Snapshot 1 and Snapshot 2" in the objects drop down. One or more of these objects will be the cause of your memory leak.
You'll likely be interested in objects that have been instantiated multiple times unexpectedly, ie per request. Or objects that would be better suited to the client instead of the server.
I found it useful to take additional snapshots to further filter the objects. I would send multiple requests to the server to simulate traffic and then compare the latest differences.
When a culprit has been identified you can try to fix the leak continuing to take snapshots until the culprit is no longer present, or instantiated the expected number of times.