You are on page 1of 8

How memory management, call stack, threading,

and the event loop works with JavaScript’s V8


engine.

In Part 1 of this article, I gave a brief overview of how


programming languages work in general and discussed the V8
engine’s pipeline in detail. This post will cover a few more
important concepts that every JavaScript programmer must
know and are not tied only to the V8 engine.

There are 2 main concerns for any programmer: Time


complexity and Space complexity. Part 1 covers the speed
and optimization part by V8 for the improved execution time of
JavaScript, this part will focus on the memory management
aspects.

Tip: Turn reusable JS code into shared components


with Bit (GitHub). Bit helps everyone build modular
JavaScript applications, easily share components between
projects and team, and build better & faster.

Share reusable code components as a team · Bit


Easily share reusable components between projects and applications to build
faster as a team. Collaborate to develop…
bit.dev

The memory heap


Orinoco logo: V8’s garbage collector

 Whenever you define a variable, constant, object, etc in your


javascript program, you need some place to store it. This
place is nothing but the memory heap.
 When the statement var a = 10 is encountered, a location in
the memory is assigned to store the value of a.
 The memory available is limited and complex programs may
have a number of variable and nested objects. This makes it
essential to make wise use of the available memory.
 Unlike languages like C, where we need to explicitly allocate
and free memory, JavaScript provides the feature of
automatic garbage collection. Once the object/variable is out
of context and will not be of use anymore, it’s memory is
reclaimed and returned to the free memory pool.
 In V8 the garbage collector is named as Orinoco and has a
really efficient process explained in this article.

Mark and Sweep algorithm


Mark and Sweep algorithm

In order to determine the objects that can be safely deleted from


the memory heap, this simple and effective algorithm is used.
The algorithm’s name itself describes its working; mark the
objects as reachable/unreachable and sweep the unreachable
ones.

The garbage collector starts with the root or global objects


periodically and moves to the objects referenced by them, and
then to the objects referenced by these references and so on. All
the unreachable objects are then cleared.

Memory leaks
Although the garbage collection is effective, the developers
should not be under the impression that they need not worry
about memory management. Managing memory is a complex
procedure and which piece of memory is not required cannot be
decided by an algorithm.

Memory leaks are parts of memory that the application needed


and used in the past and it is not needed anymore but its storage
is yet not returned to the memory pool.

Following are some of the common mistakes that cause this


memory leaks in your application.
Global variables: If you keep creating global variables, they
will stick around throughout the execution of the program even
if they are not needed. If these variables are deeply nested
objects, a lot of memory is wasted.
var a = { ... }
var b = { ... }
function hello() {
c = a; // this is the global variable that you aren't aware
of.
}

If you try to access a variable which was not declared previously,


you will create a variable in the global scope. In the above
example, ‘c’ is that variable/object that you didn’t implicitly
create using the ‘var’ keyword.

Event Listeners: This may happen when you create a lot of


event listeners to make your website interactive or maybe just
for those flashy animations and forget to remove them when the
user moves to some other page in your single page application.
Now when the user moves back and forth between these pages,
these listeners keep adding up.
var element = document.getElementById('button');
element.addEventListener('click', onClick)

Intervals and Timeouts: When referencing objects inside


these closures, the garbage collector will never clear the objects
until the closure themselves are cleared.
setInterval(() => {
// reference objects
}
// now forget to clear the interval.
// you just created a memory leak!

Removed DOM elements: This one is similar to the global


variable memory leak and very common. DOM elements exist in
the Object Graph memory and the DOM tree. This scenario is
better explained by an example.
var terminator = document.getElementById('terminate');
var badElem = document.getElementById('toDelete');
terminator.addEventListener('click', function() {memory
badElem.remove();
});

After you click the button with id = ‘terminate’ , toDelete is


removed from the DOM. But since it’s still referenced within the
listener, the allocated memory for the object is still used.
var terminator = document.getElementById('terminate');
terminator.addEventListener('click', function() {
var badElem = document.getElementById('toDelete');
badElem.remove();
});

Now, the badElem variable is a local variable and when the


remove operation completes, the memory can be reclaimed by
the garbage collector.

The Call stack


A stack is a data structure that follows the LIFO(Last in first
out) approach to store and access the data. In case of the
JavaScript engine, the stack is used to remember the location of
last executed command in a function.
function multiplyByTwo(x) {
return x*2;
}
function calculate() {
const sum = 4 + 2;
return multiplyByTwo(sum);
}
calculate()var hello = "some more code follows"

1. The engine gets to know that we have two functions in our


program.
2. Run the calculate() function.
3. Push calculate on the call stack and calculate the sum.
4. Run multiplyByTwo() function.
5. Push the multiplyByTwo function on the call stack and perform
the arithmetic operation x*2.
6. While returning with the value, pop multiplyByTwo() from the
stack and go back to calculate() function.
7. While returning from the calculate() function,
pop calculate from the stack and continue further execution
of the code.

Stack Overflow

The amount of consecutive push you can do without doing a pop


on the stack depends on the size of the stack. If you run the limit
and keep pushing, it will lead to something called stack overflow
and chrome will throw an error along with the snapshot of the
stack also called as the stack frame.

Recursion: When a function calls itself, it is called recursion.


This concept is very useful in some cases where you want to
reduce the time an algorithm takes for execution(time
complexity), but complex to understand and implement.

In the following example, the base case is never executed and


the lonely function keeps calling itself without returning
eventually causing a stack overflow.
function lonely() {
if (false) {
return 1; // the base case
}
lonely(); // the recursive call
}

Why is JavaScript single threaded?


A thread represents how many parts of programs can you
execute independently and at the same time. The easiest way to
find whether a language is single threaded or multithreaded is
by knowing how many call stacks it has. JS has one, so it is a
single threaded language.

So isn’t this a bottleneck? If I run multiple time consuming also


referred to as blocking operations like HTTP requests, the
program will have to wait for the response of each operation
before executing the next one.

To get around this problem, we need a way to do tasks


asynchronously even though we have a single thread. This is
where the event loop comes handy.

The Event Loop


Until now, most of the things that we talked about were
included in the V8, but if you search the V8 code base for
implementations of things like setTimeout or DOM, they are not
present in the V8. Other than the runtime engine, JS consists of
something called as Web APIs which are provided by the
browser to extend JS.

I don’t think I can explain this concept as efficiently as Philips


Roberts does in this video.

Conclusion
There is still a lot that goes in making a programming language
and the implementations keep changing over the years. I hope
that these two blogs have helped you in becoming a better JS
programmer and embrace the weird parts of JS. You should be
now comfortable with jargons like ‘V8’, ‘event loop’, ‘call stack’,
etc.

Most of the students (like me) start with a new framework


before learning vanilla JS. Now they should be comfortable with
what happens under the hood which in turn will help them to
write better code.

You might also like