|
| 1 | +# Capturing Heap Snapshots with Watt |
| 2 | + |
| 3 | +Heap snapshots are essential for diagnosing memory leaks, understanding memory usage patterns, and optimizing the memory footprint of your Node.js applications. Watt provides a built-in `heap-snapshot` command that captures V8 heap snapshots from running applications and streams them directly to disk. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +A V8 heap snapshot is a complete picture of all objects in your application's memory at a specific point in time. It records every object, its size, the references between objects, and where each object was allocated. This information makes it possible to find objects that should have been garbage collected but were not (memory leaks), understand which parts of your code allocate the most memory, and compare memory state across different points in time. |
| 8 | + |
| 9 | +Watt captures heap snapshots using the V8 inspector protocol (`HeapProfiler.takeHeapSnapshot`). The snapshot data is streamed from the worker thread through the runtime and directly to disk, so even large snapshots do not require buffering the entire snapshot in memory. |
| 10 | + |
| 11 | +### Key Features |
| 12 | + |
| 13 | +- **No additional dependencies**: Uses the built-in Node.js inspector module |
| 14 | +- **Streaming to disk**: Snapshot data flows directly to the output file without accumulating in memory |
| 15 | +- **Per-application snapshots**: Capture snapshots of individual applications or all applications at once |
| 16 | +- **Chrome DevTools compatible**: Output files load directly in Chrome DevTools Memory tab |
| 17 | +- **Remote capture**: Take snapshots from applications running in any environment |
| 18 | + |
| 19 | +## Prerequisites |
| 20 | + |
| 21 | +Before capturing heap snapshots, ensure that: |
| 22 | + |
| 23 | +1. **Watt is installed**: You need `wattpm` CLI installed globally or in your project |
| 24 | +2. **Application is running**: Your Watt application must be running in development or production mode |
| 25 | + |
| 26 | +```bash |
| 27 | +# Install wattpm globally |
| 28 | +npm install -g wattpm |
| 29 | + |
| 30 | +# Verify installation |
| 31 | +wattpm version |
| 32 | +``` |
| 33 | + |
| 34 | +## Basic Usage |
| 35 | + |
| 36 | +### Taking a Heap Snapshot |
| 37 | + |
| 38 | +To take a heap snapshot of a specific application: |
| 39 | + |
| 40 | +```bash |
| 41 | +# Snapshot a specific application (auto-detect runtime) |
| 42 | +wattpm heap-snapshot api-application |
| 43 | + |
| 44 | +# Snapshot a specific application in a named runtime |
| 45 | +wattpm heap-snapshot my-app api-application |
| 46 | + |
| 47 | +# Snapshot all applications |
| 48 | +wattpm heap-snapshot my-app |
| 49 | +``` |
| 50 | + |
| 51 | +The snapshot is saved in the current working directory with the naming pattern `heap-{application}-{timestamp}.heapsnapshot`: |
| 52 | + |
| 53 | +``` |
| 54 | +heap-api-application-2025-03-20T14-30-45-123Z.heapsnapshot |
| 55 | +``` |
| 56 | + |
| 57 | +### Specifying an Output Directory |
| 58 | + |
| 59 | +Use the `--dir` option to save snapshots to a specific location: |
| 60 | + |
| 61 | +```bash |
| 62 | +wattpm heap-snapshot --dir /tmp/snapshots my-app api-application |
| 63 | +``` |
| 64 | + |
| 65 | +## Analyzing Heap Snapshots in Chrome DevTools |
| 66 | + |
| 67 | +### Loading a Snapshot |
| 68 | + |
| 69 | +1. Open Chrome and navigate to `chrome://inspect` or open Chrome DevTools (F12) |
| 70 | +2. Go to the **Memory** tab |
| 71 | +3. Click **Load** and select your `.heapsnapshot` file |
| 72 | + |
| 73 | +### What to Look For |
| 74 | + |
| 75 | +The Chrome DevTools Memory panel provides several views: |
| 76 | + |
| 77 | +**Summary view** groups objects by their constructor name. Sort by **Retained Size** to find the object types consuming the most memory. Objects with unexpectedly large retained sizes are often the source of memory leaks. |
| 78 | + |
| 79 | +**Comparison view** compares two snapshots taken at different times. This is the most effective way to find memory leaks: take a snapshot before and after the operation you suspect is leaking, and the comparison view shows which objects were added. |
| 80 | + |
| 81 | +**Containment view** shows the object graph from the GC roots. This helps trace why a specific object is being retained in memory by showing the chain of references keeping it alive. |
| 82 | + |
| 83 | +**Statistics view** provides a high-level breakdown of memory usage by object type (code, strings, arrays, typed arrays, etc.). |
| 84 | + |
| 85 | +## Diagnostic Workflows |
| 86 | + |
| 87 | +### Diagnosing a Memory Leak |
| 88 | + |
| 89 | +The most effective way to identify a memory leak is to compare two snapshots: |
| 90 | + |
| 91 | +```bash |
| 92 | +# Start your application |
| 93 | +wattpm start |
| 94 | + |
| 95 | +# Take a baseline snapshot |
| 96 | +wattpm heap-snapshot my-app api-application --dir /tmp/snapshots |
| 97 | + |
| 98 | +# Exercise the suspected leaking functionality |
| 99 | +curl http://localhost:3000/api/endpoint-that-leaks |
| 100 | +# Repeat several times to amplify the leak |
| 101 | + |
| 102 | +# Take a second snapshot |
| 103 | +wattpm heap-snapshot my-app api-application --dir /tmp/snapshots |
| 104 | + |
| 105 | +# Load both snapshots in Chrome DevTools and use Comparison view |
| 106 | +``` |
| 107 | + |
| 108 | +In the Comparison view, sort by **Size Delta** or **# New** to find object types that are growing. Objects that accumulate between snapshots without being released are likely leaks. |
| 109 | + |
| 110 | +### Understanding Memory Composition |
| 111 | + |
| 112 | +To understand what your application stores in memory at rest: |
| 113 | + |
| 114 | +```bash |
| 115 | +# Start your application and let it reach a stable state |
| 116 | +wattpm start |
| 117 | + |
| 118 | +# Wait for initial startup to complete and serve some requests |
| 119 | +# ... |
| 120 | + |
| 121 | +# Take a snapshot |
| 122 | +wattpm heap-snapshot my-app api-application |
| 123 | +``` |
| 124 | + |
| 125 | +Load the snapshot in Chrome DevTools Summary view. The **Shallow Size** column shows the memory directly held by objects of each type, while **Retained Size** shows the total memory that would be freed if the object were garbage collected. |
| 126 | + |
| 127 | +### Comparing Before and After an Optimization |
| 128 | + |
| 129 | +```bash |
| 130 | +# Snapshot before optimization |
| 131 | +wattpm heap-snapshot my-app api-application --dir /tmp/before |
| 132 | + |
| 133 | +# Apply code changes and restart |
| 134 | +wattpm restart |
| 135 | + |
| 136 | +# Snapshot after optimization |
| 137 | +wattpm heap-snapshot my-app api-application --dir /tmp/after |
| 138 | + |
| 139 | +# Compare the two snapshots in Chrome DevTools |
| 140 | +``` |
| 141 | + |
| 142 | +## Tips |
| 143 | + |
| 144 | +- **Trigger garbage collection before snapshots** if possible. You can send a request to your application that triggers heavy processing, then wait a few seconds before taking the snapshot to let the GC run. |
| 145 | +- **Take snapshots under load** to see memory usage patterns during typical operation, not just at idle. |
| 146 | +- **Name your snapshots clearly** using the `--dir` option to organize before/after comparisons. |
| 147 | +- **Heap snapshots pause the application** briefly while V8 serializes the heap. For production systems, take snapshots during low-traffic periods. |
| 148 | +- **Snapshot file sizes** vary based on heap size. A typical Node.js application produces snapshots between 10 MB and 500 MB. |
| 149 | + |
| 150 | +## Next Steps |
| 151 | + |
| 152 | +After analyzing heap snapshots: |
| 153 | + |
| 154 | +1. **Identify retained objects** that should have been garbage collected |
| 155 | +2. **Trace retention paths** in the Containment view to find the root cause |
| 156 | +3. **Fix the leak** by removing the reference keeping objects alive |
| 157 | +4. **Take another snapshot** to verify the fix |
| 158 | +5. **Set up monitoring** to catch memory regressions early |
| 159 | + |
| 160 | +For related diagnostic tools: |
| 161 | + |
| 162 | +- [Profiling Applications with Watt](profiling-with-watt.md) for CPU and heap allocation profiling |
| 163 | +- [Debugging with REPL](debugging-with-repl.md) for interactive runtime inspection |
| 164 | +- [Metrics and Monitoring](metrics.md) for ongoing memory monitoring |
0 commit comments