Garbage Collection
Introduction
“Reachable” values are those that are accessible or usable somehow. They are guaranteed to be stored in memory.
Garbage collection is performed automatically. We cannot force or prevent it.
Objects are retained in memory while they are reachable.
Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole, as we’ve seen in the example below
Simple Example
let user = {
name: "John"
};
user = null;
The object is created
However after set to null, there is no reference on the object, so the object can be collected and free the memory
// user has a reference to the object
let user = {
name: "John"
};
let admin = user;
user = null;
The object cannot be collected as it is referenced by admin unless we set admin to null too
Interlinked objects
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
In order to delete the man , we need to remove family.father and family.mother.husband
if we set family to null then, both woman and man can be collected
GC Trace
node --trace-gc script.mjs
It should output the following
[13973:0x110008000] 44 ms: Scavenge 2.4 (3.2) -> 2.0 (4.2) MB, 0.5 / 0.0 ms (average mu = 1.000, current mu = 1.000) allocation failure
13973
PID of the running process
0x110008000
Isolate (JS heap instance)
44 ms
The time since the process started in ms
Scavenge
Type / Phase of GC
2.4
Heap used before GC in MB
(3.2)
Total heap before GC in MB
2.0
Heap used after GC in MB
(4.2)
Total heap after GC in MB
0.5 / 0.0 ms (average mu = 1.000, current mu = 1.000)
Time spent in GC in ms
allocation failure
Reason for GC
Types of GC
Introduction


Initially, objects are in the Nursery region.
If they survive the first round of GC, they will be moved to the Intermediate region
If they survive the second round of GC, they will be moved to the Old Generation region.
For each generation, the algorithm is different:
Young generation — Minor GC (Scavenger)
Old generation — Major GC (Full Mark-Compact)
Mark-sweep


Mark: mark the roots as “reachable”
Visit and recursively mark objects directly or indirectly referenced by roots as “reachable”
Sweep: unmarked ones are removed
Compaction: To reuse the small and scattered memory gaps left behind by dead objects, we would process the “compact” task: copy surviving objects into other pages and free the old page.
Scavenger

Divided the young generation into two parts, we only have to limit the moving behavior within the page. Instead of focusing on the dead objects, we only focus on the surviving ones. We move all surviving objects to a contiguous chunk of memory within the page, and thus the from-space has become the “whole garbage.” Free the “From-Space” all!
After moving, To-Space becomes From-Space and vice-versa. And the From-Space becomes empty, and new allocations can be done in the From-Space.
Space for the young generation is limited to 16MB, and it would quickly reach its limit. Objects that survive a second GC are evacuated into the old generation rather than To-Space.
Clean GC Manually
Only work when expose-gc flag is available
Here is an example
global.gc();
console.log(process.memoryUsage());
let vm = new WeakMap();
let key = new Array(1000000);
vm.set(key,1);
global.gc();
console.log(process.memoryUsage());
key = null;
global.gc();
console.log(process.memoryUsage());
node --expose-gc index.js
Reference
Last updated
Was this helpful?