In diagnosing memory leaks, one of the most useful tools in a developer's aresenal is the heap dump, or heap snapshot, which gives us insight into what objects are allocated on the JavaScript, and how many of them.
The Old Way
Traditionally, in Node.js, we've had two options for creating heap dumps.
- Using the
heapdump
module. - Attaching a Chrome DevTools instance and using the Memory tab to create a heap snapshot.
In cases where it's feasible and simple, the second option is usually best, since it requires no additional software, and has a simple point-and-click interface to get the job done.
In production environments, it's often not an option, so users are left using the heapdump
module. While this generally works without issue, there is an additional compilation step and a module to install in order to get this done. These are obivously not insurmountable hurdles, but they can get in the way of solving a problem quickly.
The New Way
The good news is that in newer versions of Node.js, you don't need the external module, since heap dump functionality is now part of the core API, as of Node.js v12.
To create a heap snapshot, you can just use v8.getHeapSnapshot()
. This returns a readable stream, which you can then pipe to a file, which you can then use in Chrome DevTools.
For example, you can make a function like this that you can call whenever you want to create a heap dump file.
const fs = require('fs');
const v8 = require('v8');
function createHeapSnapshot() {
const snapshotStream = v8.getHeapSnapshot();
// It's important that the filename end with `.heapsnapshot`,
// otherwise Chrome DevTools won't open it.
const fileName = `${Date.now()}.heapsnapshot`;
const fileStream = fs.createWriteStream(fileName);
snapshotStream.pipe(fileStream);
}
You can call this function on a regular basis using setInterval
, or you can set a signal handler or some other mechanism to trigger the heap dumps manually.
This new API function is available in all currently supported release lines of Node.js except for v10, where you'll still need the heapdump
module for similar functionality.
Feel free to use the snippet above in your own applications whenever trying to diagnose memory leaks in the future. Happy debugging!
Top comments (5)
Or with the new fs.promises, do:
there's a convenient api,do:
I have tried using this method to take the heap snapshots. It blocks the app from running and it also takes around 20-40 seconds to generate the heap snapshot.
Do we have any better way to do it without blocking the app for 20-40 seconds?
There is other lightweight module to take heap snapshots (the snapshots are a bit different, but maybe could be useful for you): github.com/v8/sampling-heap-profiler
Here you have a talk about this module: youtu.be/hliOMEQRqf8?t=1496
Hope it helps! 😁
Heck I don't even get that far. V8 doesn't seem to stream the snapshot data at all, despite the API. So PM2 kills the process before I ever get a single byte in the output file. Presumably if PM2 didn't kill it OOMKiller would.
If I'm already out of memory, maybe tripling memory usage is not the best of all plans.