DEV Community

Cover image for Node.js Heap Dumps in 2021
Bryan English
Bryan English

Posted on

Node.js Heap Dumps in 2021

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.

  1. Using the heapdump module.
  2. 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);
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
voxpelli profile image
Pelle Wessman • Edited

Or with the new fs.promises, do:

await fs.promises.writeFile(
  `${Date.now()}.heapsnapshot`,
  v8.getHeapSnapshot()
);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ejayyoung profile image
eJay

there's a convenient api,do:

v8.writeHeapSnapshot(`${Date.now()}.heapsnapshot`)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
austonpramodh profile image
Auston Pramodh Barboza

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?

Collapse
 
nadrixa profile image
Nadrixa

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! 😁

Collapse
 
jdmarshall profile image
Jason Marshall

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.