In programming languages, garbage collection is a crucial concept dealing with automatic memory management. The programming languages which enable garbage collection provide developers with various garbage collecting engines. These engines work efficiently to clean the memory space. A garbage collection engine looks for the objects that are no longer under the use of the program. The engine deletes or removes these objects to utilize memory and resources efficiently.
There are various types of garbage collectors. Some of these types are the following:
JavaScript assigns memory to the objects at their declaration automatically. The developers do not have to worry about object memory allocations. A concept of reachability in JavaScript is associated with the memory allocation to objects. In JavaScript, the reachable values are the objects which are somehow usable for the program. Following are some of JavaScript’s reachable objects or values for clarification:
For the low-level languages, the developers have to manually track the point at which they no longer need to allocate memory to some specific objects. Developers have to free some space by removing such objects manually. However, for advanced languages such as Javascript, their engine keeps track of all these objects and removes them when they become unreachable.
The concept of garbage collection relies mainly on references. If an object can implicitly or explicitly access another object, the former has a reference to the latter. For example, a Javascript object has an implicit reference to its prototype and an explicit reference to its property values. JavaScript possesses various garbage collection algorithms to use memory resources effectively.
The “reference counting garbage collection algorithm” is one of the garbage collector’s most basic JavaScript algorithms. This algorithm states that an object is “useful” if other objects are referencing it. In other words, the algorithm narrows down the problem and determines if the object is still “useful” for the program or not. If no other object is referencing a specific object, that object is considered garbage. The algorithm collects the object and prepares the memory to re-allocate to another object.
A simple example of using the reference counting algorithm is the following:
var testing_obj = { i: { j: 10 } }
In this example, there are two objects. One is referencing the other with its property. The second object is assigned to the testing_obj variable. So far, there is no chance of garbage collection here.
var new_Obj = obj; obj = 10;
Even though there is another object, still the new_obj is referencing the previous object. There is still no chance of garbage collection.
var n_Obj = new_Obj.i;
In this scenario, there are two references to the “i” object. Now there is a chance of garbage collection here.
new_Obj = ‘testing’; n_Obj = null ;
The “i” does not have any reference now. Therefore, it qualifies for garbage collection now.
The reference counting algorithm has a limitation regarding a circular reference. If there is an object whose properties reference one another, it creates a circular reference. Even if these properties are out of scope after their function call, the reference counting algorithm can not remove them as they will still be pointing to each other. Therefore, circular references become common causes of memory leakage in programs.
The “Mark and Sweep garbage collection algorithm” considers removing the objects once they are no longer reachable. This algorithm works on the concept of root objects. A root is a global object in JavaScript. In this case, the garbage collection algorithm starts with the root objects. It identifies all the objects that roots refer to, and the further objects to that these referenced objects are referring. Therefore, it finds all the reachable and non-reachable objects. Finally, the algorithm collects all the non-reachable objects and removes them to free the memory.
This algorithm is advanced and improved from reference counting and other algorithms. There the modem browsers contain the mark and sweep garbage collector. Moreover, most of the garbage collection improvements such as generational, concurrent, incremental, and parallel garbage collection are the implementations of this algorithm.
In the case of the mark and sweep algorithm, the objects having no reference from the global object after the function call return will be unreachable. Therefore, there will no longer be a problem with a circular reference.
The mark and sweep algorithm will automatically release the memory after determining the unreachable objects in any program. However, there are some situations when a developer seeks convenience in manually deciding when and what objects to make unreachable. Therefore, the developers must make some objects unreachable following their plans explicitly. Moreover, since 2019, there has been no explicit or programmatic way of triggering garbage collection in JavaScript.
There are numerous reasons for memory leakage in an application. The developers can keep an eye on these reasons and avoid them to prevent memory leakage and use the memory allocation efficiently for an application to work smoothly. Some common reasons for memory leakage in an application are:
Node.js provides various additional tools and options for configuring and debugging the memory issues for JavaScript, which are not usually available or executed within a browser environment. Therefore, for a high-level programming language like JavaScript, there are various additional tools and algorithms to manage memory resources and perform garbage collection effectively automatically.