Javascript memory management detailed parsing

  • 2020-03-27 00:09:15
  • OfStack

introduce

Low-level languages, such as C, have low-level memory management commands, such as malloc() and free(), which require the developer to manually free memory. However, the case of high-level languages like javascript is different. When objects (objects, strings, etc.) are created, the memory is allocated. When they are not used, the memory will be automatically recycled. Because of garbage collection, developers of advanced languages like javascript have the wrong idea that they can ignore memory management.

Memory life cycle

The memory life cycle is basically the same regardless of the programming language.

Allocate the memory you need

2. Use it for read and write operations

Release resources when memory is not needed

Steps 1 and 2 are obvious for all languages. As for step 3, the low-level language requires the developer to explicitly execute it. For a high-level language like javascript, this is done by the parser, so you don't notice.

Assign operations in javascript

Initialization of the value

Javascript allocates memory when assigning values to variables.


var n = 123; //Allocate memory for Numbers
var s = "azerty"; //Allocate memory for strings

var o = {
  a: 1,
  b: null
}; //Allocates memory for the object object that contains the property value

var a = [1, null, "abra"]; //Allocates memory to an array containing values

function f(a){
  return a + 2;
} //Allocates memory to functions (functions are callable objects)

//A function expression is also an object, and memory is allocated
someElement.addEventListener('click', function(){
  someElement.style.backgroundColor = 'blue';
}, false);

The allocation is done through a function call

After some functions are executed, the same object allocation occurs.


var d = new Date();
var e = document.createElement('div'); //Assign a DOM element

Some methods assign new values or objects.

var s = "azerty";
var s2 = s.substr(0, 3); //S2 is a new string
//Since strings are immutable, javascript creates a new string for the contents of the [0, 3] range

var a = ["ouais ouais", "nan nan"];
var a2 = ["generation", "nan nan"];
var a3 = a.concat(a2); //Combine a and a2 to create a new array

The use of values

The use of a value is essentially a read and write operation on the allocated memory. These operations include reading and writing to a variable or an object's properties, or passing arguments to a function.

Free memory when no longer needed

Most memory management problems occur at this stage. The hardest thing to do is to decide that the allocated memory is no longer needed. This often requires the developer to determine when the program no longer needs memory and to free up its resources.

The high-level language's parser is embedded with a program called the garbage collector, whose job is to track the allocation and use of memory, determine whether it is needed, and perform resource release operations when it is no longer needed. He can only get an approximation, because determining whether a memory is needed is an uncertain problem (which cannot be solved by an algorithm).

The garbage collection

As mentioned above, we cannot automatically determine that "memory is no longer needed" accurately. So, garbage collection has limitations on the solution to this problem. This section explains the concepts necessary to understand the major garbage collection algorithms and their limitations.

reference

One of the main concepts in garbage collection is reference. In memory management, when an object explicitly or implicitly USES another object, it refers to another object. For example, a javascript object has an implicit reference to the stereotype and an explicit reference to the value of its property.

Here, the concept of objects goes beyond the traditional javascript concept of objects to include both functional and global scopes.

Garbage collection using reference counting algorithms

The following is an optimal algorithm that introduces the concepts of "objects are no longer needed" and "no other objects reference this object." When the object's reference pointer goes to zero, it is considered recoverable.

Example:


var o = { 
  a: {
    b:2
  }
}; //Two objects are created. One object (a) is referenced by the other object (the object referenced by o) and takes a as its property
//This object is again referenced by the variable o
//Obviously, no object can be recycled at this point

 
var o2 = o; //The variable o2 again references this object
o = 1; //O no longer references the object, only o2 still references the object

var oa = o2.a; //Oa refers to the property object a of o2
//This object is referenced by two other objects, the property a of o2 and the variable oa

o2 = "yo"; //This object is no longer referenced by other objects, but its property a is still referenced by the oa variable, so it cannot be released yet
oa = null; //Now that property a is no longer referenced by another object, the object can be recycled

Limitation: circulation

This algorithm has its limitations. When one object references another object, the garbage collector will not collect them even if they are no longer needed when circular references are formed.


function f(){
  var o = {};
  var o2 = {};
  o.a = o2; //O reference o2
  o2.a = o; //O2 reference o

  return "azerty";
}

f();
//The two objects are created and referred to each other
//After the function call ends, they do not escape from the function scope, and while they are not used, they are not released
//This is because the reference counting algorithm determines that garbage collection cannot be performed on an object as long as it is referenced

Real-life examples
Ie6, 7, the use of reference counting algorithm on the dom object, there is a memory leak problem.


var div = document.createElement("div");
div.onclick = function(){
  doSomething();
}; //Div references the event handler with the click property
//When the div variable is accessed in the event handler, a circular reference is formed that causes neither object to be recycled, resulting in a memory leak

Mark-sweep algorithm

He introduced the concepts of "objects are no longer needed" and "objects are not accessible (objects are not reachable)." The algorithm assumes that there is a series of root objects (the root object in javascript is the global object), and every once in a while, the garbage collector starts with the root object, iterates over all the objects it references, then iterates over all the objects it references, and so on. In this way, the garbage collector can obtain all accessible objects and reclaim those that are not.

This algorithm is better than the previous one. Objects referenced by 0 are set to be inaccessible, and it avoids the annoyance caused by circular references.

As of 2012, most modern browsers use this "mark-sweep algorithm" garbage collector. The area of JavaScript garbage collection (generation/incremental/concurrent/parallel garbage collection) has improved its associated algorithms over the past few years, but the garbage collection algorithm itself (mark-sweep algorithm) and "how to determine if an object is no longer needed" have not.

Cycles are no longer a problem

In the first example, after the function call, the two objects are not referenced by the global object, nor by the object referenced by the global object. Therefore, they are marked as inaccessible objects by the javascript garbage collector. This also happens in the second example, where divs and event handlers are released when they are marked as inaccessible by the garbage collector.

Restriction: objects need to be explicitly marked as inaccessible

This approach to tagging is limited, but we are not exposed to it in our programming, so we care little about garbage collection.


Related articles: