Javascript basics: Memory management.

Swati Sucharita
7 min readAug 22, 2020

--

This article is part of my javascript basics series where I am trying to explain basic javascript concepts. If you want to know more about this series, you may want to check my earlier articles about hoisting in javascript and Javascript event loop & concurrency.

Memory management means how the memory is allocated, used and cleared. As we can see it has 3 steps.

  • Memory allocation: Memory is allocated by the operating system.
  • Memory usage: Read/write operations are performed in the allocated memory.
  • Memory de-allocation: Memory is released.

In languages like C, we have malloc() and free() to allocate and deallocate memory. So along with taking care of the solving the business problem, managing data structures, developers also have to take care of memory allocation and deallocation.

In Javascript, memory allocation and deallocation happens implicitly. For instance, when a variable is declared, some memory is allocated in the heap. When the variable is not required anymore, javascript has a process called garbage collection, which frees the memory.

This automatic memory management nature of javascript can make the developer get a false impression that it is not required to care about memory management, which can affect the performance of the web application.

Why we need memory management:

  • Memory is scarce: Even though amount of memory available in the computer has improved tremendously in last few decades, it is still limited. All the variables, executables, code for operating system is stored in the memory. We should be mindful to use it and share it.
  • If we use more memory than we optimally need, it can make our application consistently slow.
  • We have more number of garbage collection cycles, which will pause the engine for brief period of time. This will block the application more frequently. As a result will lead to bad user experience.
  • Bad memory management can make the application increasing slow.

Let’s see how automatic memory management works in Javascript

  • Memory Allocation: When any variable, expression, function is declared some memory is allocated for it.
  • Memory Usage: When Read/Write operations happen on the variables, the memory is used.
  • Memory Release: When javascript figures out the allocated memory is “not required anymore”, it frees the memory. A garbage collection cycle runs in the engine and it tries figuring out which memory is not in use anymore and releases it. Let’s see how this garbage collector decides which memory to clear.

Garbage Collection

Garbage collection is responsible for clearing the memory. It runs for a brief period of time in some time. The machine halts for some time when the garbage collector performs its job. Therefore frequent garbage collection cycles are not good for the web app performance.

  • Reference counting garbage collection: Using this algorithm, the garbage collector tries to find out references to the objects or the code. If no reference found for it, garbage collector can clear the memory allocated for it.

problem with this type of garbage collection is cyclic references. Suppose two objects referring to each other, but nobody is using them. Even when memory can be released for them, due to this cyclic reference, the garbage collector will not collect this memory.

  • Mark and Sweep: Using this algorithm, the program runs one Mark cycle followed by a Sweep cycle. In mark cycle, it starts the execution from the Window or global. It keeps marking all the memories it is able to access. In Sweep cycle, it traverses the whole heap. Frees the unaccessible memories and resets the mark for marked memories.

In the above image, we can consider the red node as the root like window or global. We start marking from the root node. We mark all the nodes accessible from the root node. All other nodes are swept off. So cyclic references are not a problem anymore.

Here is an illustration of mark and sweep cycle by Minko Gechev

So we saw how memory is allocated, used and released. It all looks good. Let’s now come to what is the problem in it. Problem occurs when memory is allocated, but never released back to the OS. This condition is called Memory leak.

Garbage collection process can be a little un-predictable. Garbage collection process is an approximation since the general problem of determining whether or not a specific piece of memory is still needed is undecidable. How the garbage collection process is triggered, that also plays an important role.

Let’s take a scenario.

  • A sizeable amount of memory is allocated.
  • Memory is used.
  • No other memory allocation happens. Hence GC is not triggered anymore.

In this case, even if the chunk of memory is not used, it is not also released, as the garbage collector process doe not triggered.

Let’s see how can we avoid Memory leak:

High level javascript languages like Javascript, manages its own memory management process. But as we saw above, it uses some algorithm to release the memory and determining a specific piece of memory is required or not is still undecidable. As developers, we have to keep in mind that we are not using more memory than optimally required or we are not holding any un-required memories.

Here is some examples which can lead to Memory leak:

  1. Global Variables: Javascript considers undeclared variables to be global variables. So if we use any variable without declaring it, javascript adds it to the global scope. It is never released even if it is not required anymore.

To avoid this, we should also declare our variable in its scope. It enables garbage collector collect this memory when it’s done with its job.

This is the right way to declare a variable and use it. We can enable “strict” mode to avoid such scenarios.

2. Closures: Closure is a key javascript feature. When there is a function, that is returning another function, the inner function has access to variables declared n the outer function.

In this way, it is possible that, the inner function is holding some unused memory, that can lead to memory leak.

In this example, variable res is not required, but it keeps holding lo of memory. It can cause memory leak.

I ran code, in my browser. Let’s look at the memory allocation using chrome dev tool.

We can see memory allocation keeps increasing.

There is an amazing article about this by Meteor.

3. Event listeners: Sometimes event listeners are added to the DOM. But developers do not removed it when the DOM node is gone. Modern browsers remove these event listeners when the DOM node is not present anymore. But the older browsers do not remove these listeners and keep holding the memory. We should be mindful about removing the listeners when it is scope is destroyed.

It is also applicable for the timers. When a timer is set, it has to be removed as well.

4. Out of DOM references: DOM node references should not be stored in other data structures. It can lead to memory leak. Suppose we store all the <li> items in an object. Then we removed the all the <li>s, we have to keep in mind, we have remove the references from the object as well. Otherwise, it will not release the memory allocated for it.

These are few examples how we can avoid memory leaks. We should be mindful about memory allocation, usages and release during development.

Congratulations! We are at the end of the article. Hope it helps you out.

Thanks for reading!

--

--