Inspect Node.js Memory Programmatically with V8

Monitoring memory usage is crucial for maintaining stable and performant Node.js applications. This article provides a straightforward guide on how to use the built-in v8 module in Node.js to programmatically inspect memory allocation. You will learn how to retrieve general heap statistics, analyze specific heap space distributions, and generate heap snapshots for deep-dive debugging without relying on external APM tools.

Accessing the V8 Module

Node.js provides the v8 module out of the box, meaning you do not need to install any external dependencies. To start inspecting your application’s memory, import the module into your script:

const v8 = require('v8');

Retrieving Heap Statistics

The most common way to inspect memory allocation is by using v8.getHeapStatistics(). This method returns an object containing metrics about the V8 heap helper, such as the total heap size, the used heap size, and the physical limit the heap can grow to.

const heapStats = v8.getHeapStatistics();

console.log(`Total Heap Size: ${(heapStats.total_heap_size / 1024 / 1024).toFixed(2)} MB`);
console.log(`Used Heap Size: ${(heapStats.used_heap_size / 1024 / 1024).toFixed(2)} MB`);
console.log(`Heap Size Limit: ${(heapStats.heap_size_limit / 1024 / 1024).toFixed(2)} MB`);

Key Properties Explained:

Analyzing Heap Space Statistics

To inspect how memory is distributed across different V8 generation areas, use v8.getHeapSpaceStatistics(). V8 divides memory into different spaces (like the new space for short-lived objects, and the old space for long-lived objects) to optimize garbage collection.

const heapSpaces = v8.getHeapSpaceStatistics();

heapSpaces.forEach(space => {
  console.log(`Space: ${space.space_name}`);
  console.log(`  Size: ${(space.space_size / 1024 / 1024).toFixed(2)} MB`);
  console.log(`  Used: ${(space.space_used_size / 1024 / 1024).toFixed(2)} MB`);
  console.log(`  Available: ${(space.space_available_size / 1024 / 1024).toFixed(2)} MB`);
});

This breakdown is particularly useful for identifying whether memory pressure is building up in the old_space (indicative of long-term leaks) or the new_space.

Generating Heap Snapshots Programmatically

When you detect abnormal memory growth through statistics, you can programmatically generate a heap snapshot. A heap snapshot records all active JS objects and allocation paths, which can then be loaded into Chrome DevTools for visualization.

Use v8.writeHeapSnapshot() to save the snapshot to a file:

const fs = require('fs');
const path = require('path');

function captureMemorySnapshot() {
  const filename = path.join(__dirname, `snapshot-${Date.now()}.heapsnapshot`);
  const filepath = v8.writeHeapSnapshot(filename);
  console.log(`Heap snapshot successfully written to: ${filepath}`);
}

// Example usage: Trigger snapshot when used heap exceeds 80% of limit
const stats = v8.getHeapStatistics();
if (stats.used_heap_size > stats.heap_size_limit * 0.8) {
  captureMemorySnapshot();
}

Once the .heapsnapshot file is generated, open Google Chrome, navigate to DevTools > Memory, right-click the Profiles sidebar, select Load, and upload your file to inspect the object allocation tree.