Before we move on...
i want to give an entirely too brief introduction into the gc
Garbage Collection
These terms are V8 specific (sorry bun) but i bet there are similar concepts in JSC. These definitions have been taken from V8's Blog on GC
How this code "works"
let a = {};
const b = [a];
const c = { ref: a };
a.foo = 69;
both b
and c
will reflect the same value, because they are pointing to the
same object.
But what happens here?
a = undefined
b.pop();
delete c.ref
our original object, 0xdeadbeef
, has been completely abandoned.
There are two types of GC
- Major: walks all the objects from the root checking for what to be removed (typically slow)
- Minor: walks all the "new" objects from special roots checking for what to be removed (typically fast)
Major GC: Marking and Sweeping
In javascript there are "root" objects.
Lets look at a quick example of a root
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<script>
const a = {};
let b = {};
setTimeout(function() {
b = undefined;
}, 1000);
</script>
</body>
</html>
Major GC Before b = undefined
Major GC After b = undefined
Compaction
"The major GC also chooses to evacuate/compact some pages, based on a fragmentation heuristic. You can think of compaction sort of like hard-disk defragmentation on an old PC. We copy surviving objects into other pages that are not currently being compacted (using the free-list for that page). This way, we can make use of the small and scattered gaps within the memory left behind by dead objects." - v8 trash talk
Minor GC (Scavenge)
This is the second form of GC in V8 and this follows the "The Generational Hypothesis"
"'The Generational Hypothesis'
This basically states that most objects die young. In other words, most objects are allocated and then almost immediately become unreachable, from the perspective of the GC" - v8 trash talk
How Minor GC works
Its more complicated than the major gc, but effectively it uses a few techinques and a different set of "roots" to calculate life. 1/2 of the minor GC space is left empty and objects are copied "From Space" to "To Space" every GC. Only the "alive objects" are copied over to "To Space"
To Recap
Major GC (Full Mark-Compact): A stop the world, full heap crawl of all the objects created
- typically more rare
- typically takes significantly longer than Minor
- Sometimes has to compact a memory region due to fragmentation
Minor GC (Scavenger): GC collecting only from the "nursery" or young generation.
- typically frequent
- relatively "fast"
How Generational GCs Work
This is a brief introduction to GC
Hopefully the point that got across. {}
are a bit more expensive than you
may have realized. Perhaps you will think more about Array#map and
Array#filter from here on out
- really short lived objects can be cleaned efficiently
- longer lived, across a couple promises, those can be worse overall
Some Notes
Major and Minor GCs do have some parallelism to it and even runs while JavaScript is running. The article linked goes into great detail about it and its quite clever. But remember, if you have a program getting tons of messages from the internet, and you are getting bogged down by GC, and its not a powerful machine, like mine, GC can have a more disproportional effect