为何process.memoryUsage().heapUsed数值持续增长?附复现代码
I wrote this code expecting that heapUsed wouldn't grow after clearing and setting a Timeout, but in reality it keeps rising:
let process = require('process'); console.log('initial', process.memoryUsage().heapUsed); let timeout; function happen() { console.log('process', process.memoryUsage().heapUsed); clearTimeout(timeout); // Clear previous timeout timeout = setTimeout(happen, 500); // Set next timeout } happen();
Why is this happening?
Great question! Let's break down why you're seeing this behavior:
Garbage Collection isn't instantaneous
V8 (the JavaScript engine Node.js uses) doesn't run garbage collection (GC) every time a small amount of memory is allocated. It waits until memory usage hits specific thresholds (based on heap size, allocation rate, etc.) before kicking in. The risingheapUsedyou see is just temporary uncollected memory—if you let the program run long enough, or trigger GC manually, you'll see the value drop back down.console.logadds unexpected memory overhead
Every call toconsole.logcreates string objects to format your output, and these objects stick around in memory until GC collects them. Additionally, most terminal environments buffer output, which means those logged strings are held in memory temporarily even after they're printed to the screen. This adds up with each 500ms call tohappen().Timer internal state cleanup takes time
When you callclearTimeout, Node.js marks the timer as inactive, but some internal bookkeeping objects or references might not be immediately released. These tiny bits of memory will be cleaned up eventually when GC runs, but they contribute to the short-term heap growth you're observing.
How to verify this
If you run your Node.js script with the --expose-gc flag, you can manually trigger garbage collection to see the heap usage drop:
let process = require('process'); console.log('initial', process.memoryUsage().heapUsed); let timeout; function happen() { console.log('before gc', process.memoryUsage().heapUsed); global.gc(); // Manually trigger GC console.log('after gc', process.memoryUsage().heapUsed); clearTimeout(timeout); timeout = setTimeout(happen, 500); } happen();
You'll notice that after calling global.gc(), heapUsed drops back close to the initial value, confirming that the growth was just uncollected temporary memory.
内容的提问来源于stack exchange,提问作者Sunil Choudhary

