A 4-minute primer to memory management and garbage collection in Node.js
Node.js manages memory using different memory spaces.
In this article, we will learn in under 4 minutes what the different spaces are, how they relate to each other and what it means when your Node.js script throws a FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
.
So let's get started!
The different memory spaces
Nodes.js uses two main memory spaces to store function calls, primitive values, and objects in memory: stack memory and heap memory:
Stack memory
Stack memory or "the stack" is used for storing function calls, local variables, and control flow in so called stack frames.
When a function completes, a program ends or an exception unwinds the stack, the stack memory is freed again.
Objects are not stored in stack memory. Stack memory only contains references to objects. The objects themselves are stored in heap memory.
Heap memory
Heap memory or "the heap" is memory allocated for objects.
Heap memory is divided into a "new space" and an "old space":
The "new space" is further subdivided into two equally sized semi-spaces: the "from space" and the "to space":
When objects are created, they are added to the "from space" in the "new space".
When the "from space" is full, garbage collection is triggered inside the "new space".
Garbage collection in the "new space" is a fast and frequent process. Objects that are still referenced in your application are copied from the "from space" to the "to space":
The "from space" is then emptied and the "to space" and "from space" are swapped.
Objects that survive multiple garbage collections in the "new space" are moved to the "old space".
When garbage collection runs in the "old space", objects that are no longer referenced in your application are selectively removed from the "old space":
Garbage collection in the "old space" is less frequent but more intensive.
When the "old space" is full, a FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
is thrown:
<--- Last few GCs --->
ze[59239:0x148008000]
462 ms: Mark-Compact (reduce) 15.3 (16.8) -> 15.1 (17.3) MB, 0.88 / 0.00 ms (+ 0.3 ms in 7 steps since start of marking, biggest step 0.1 ms, walltime since start of marking 4 ms) (average mu = 0.754, current mu = 0.737) finalize[59239:0x148008000]
468 ms: Mark-Compact (reduce) 15.9 (17.5) -> 15.3 (17.5) MB, 3.21 / 0.00 ms (+ 0.3 ms in 8 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 5 ms) (average mu = 0.551, current mu = 0.398) allocati
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Phew, that was a lot, so let's summarize what we learned.
Summary
Nodes.js uses two main memory spaces to store function calls, primitive values, and objects in memory: stack memory and heap memory.
Stack memory or "the stack" is used for storing function calls, local variables, and control flow in so-called stack frames.
When a function completes, a program ends or an exception unwinds the stack, the stack memory is freed again.
Objects are not stored in stack memory but in heap memory.
Heap memory is divided into a "new space" and an "old space".
Garbage collection in the "new space" is frequent and very fast.
When objects survive multiple garbage collections in the "new space", they are moved to the "old space".
Garbage collection in the "old space" is less frequent and very intense.
When the "old space" is full, a FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
is thrown.
That's itβyou made it, congratulations! π
When you now receive a memory error in Node.js, you'll be able to understand what's happening and why! π
Happy coding! π πββοΈ