Sal
This blog post is a part of the "Web Development - Frontend" series.This blog gives a basic overview of frontend memory management in Javascript. Written by Gunjeev Singh

Introduction

Memory is the most sacred resource for all developers. Products’ efficiency depends on how well they manage memory. Memory Management is one of the top required skills for all development jobs. This is why it becomes exceedingly important to read, learn and practice memory management. This blog is the perfect starting point for making yourself familiar with all the technicalities related to memory management in Javascript.

Memory Cycle and Storage

Before we dive deep into learning how exactly memory is managed, we need to have a look into some more fundamental concepts like what exactly do we mean by memory cycles, and where exactly is data stored in the frontend.

When we talk about data in the frontend, we usually refer to Javascript variables and objects which would be created when the user performs a certain task to which they are associated. For example, some Javascript variables might be created whenever the user loads the website, clicks on a button, etc. All such data instances are stored in the browser session and/or cookies which are stored locally, on the local hard disk.
Please Note: Images, text, etc which are being rendered on the DOM of the browser is NOT what we refer to as data in the frontend. That data is stored in databases and cloud services and are called through server calls.

Memory Life Cycle

Javascript automates the memory management process for us, but it is still important to know what all steps are a part of the memory life cycle, because that enables us to utilise memory in a more optimal way, and also prevent some leakages which may occur during the garbage collection.
Regardless of the language, the memory life cycle generally comprises of the same elements or stages:

1. Memory Allocation
2. Memory Usage
3. Memory Release
memoryJS1.png

The 2nd part is explicitly performed in all languages, but part 1 and 3 are explicit in low level languages like C whereas they are implicit in high level languages like Javascript. Let us now dive deeper into both these concepts.

Memory Allocation

When we talk about memory allocation, we need to discuss two things here - One, how is the memory allocated, and Two, where is this memory allocated. In Javascript, memory is allocated automatically when a variable, object, array or function is initialised. The memory is allocated in the Stack and in the Heap. Primitive Data Types (numbers, booleans, strings) are and References (Pointers) are stored in the stack, while Objects, functions and arrays are stored in the Heap.

Memory Allocation in the Stack

In Javascript, the stack memory stores primitive data types and references. The stack has a “First Come, Last Out” Policy. To store data in the stack, programmers just need to initialise it in their code.

var number = 5; //allocates memory for a number in the stack
var word = "name"; //allocates memory for a string in the stack

hese variables are stored in the stack as the following diagrammatic representation shows:

memoryJS2.png

Memory Allocation in the Heap

The heap, unlike the stack, stores objects, functions and arrays. Another difference memory in the heap has with respect to that stored in the Stack that the amount of memory required in the stack is known at compile time; i.e; before we actually run the code, whereas memory in the heap is dynamic, hence it is only known to us at run time. To understand memory allocation in the heap and its connection with the stack, let us take the following example.

const person = {
      name : 'Gunjeev',
      age : 19,
};

Now look carefully that the object “person” is not a primitive data type, and hence is stored in the heap, but variables ‘name’ and ‘age’ are primitive, and hence their actual values are stored in the stack.

memoryJS3.png

Now, you may be wondering what this “Person” entity is doing in the stack? The “Person” in the stack is nothing but a reference, or pointer so to say, to the actual object which is stored in the heap. This is how memory allocation happens in Javascript.

.

Memory Release or Garbage Collection

When memory is no longer in use, it must be released. If this is not taken care of, memory blocks may occur. Again, even this procedure is taken care of automatically by Javascript. The problem with this is that whether or not specific memory is still required is something which is undecidable during runtime, which means that there can't be an algorithm that's able to collect all the memory that's not needed anymore exactly when it becomes useless. There are some algorithms which do have a good approximation over others which do not. Let us discuss the two main algorithms below:

1. Reference-counting garbage collection - In this algorithm, the Javascript engine looks for objects in the heap which do not have a reference that points to them. This is the easiest way to approximate which memory instances are not required anymore. When the JS Engine finds objects without a reference, it releases their memory. Despite being the easiest way to approximate, it is not the most used one, as it does not release memory of objects with cyclic references.

2. Mark-and-sweep algorithm - In this algorithm, the problem of objects pointing to one another (cyclic references) is resolved. This algorithm does not simply search for objects which do not have references, it searches for objects which do not have a reference to the root object in the stack. The root object, in browsers, is simply the window. So if an object is not connected to the root by any means, it is removed and its memory is released and collected.

Key Takeaways

1. In Javascript, memory management is automatic.
2. A memory life cycle consists of allocation, usage and release.
3. Memory is allocated in the stack and the heap, primitive data types in stack, objects, functions and arrays in the heap.
4. Objects in the heap have references to the stack
5. Garbage collection is done by algorithms which approximate which memory instance is not required and should be deleted.


This blog was written by our core team member Gunjeev Singh