Let’s look at JavaScript’s garbage collection mechanism

Time:2020-11-27

Garbage collection mechanism of JS

JS will automatically allocate memory when creating variables, and automatically release memory periodically when not in use. The release process is called “garbage collection”. This mechanism has both advantages and disadvantages. On the one hand, automatic memory allocation reduces the burden of developers, and developers don’t have to pay too much attention to memory usage. On the other hand, because it is automatic recycling, it is easy to cause confusion if the recycling mechanism is not clear, and confusion is easy to cause “memory leakage”. Because of the automatic recovery, there is a “whether the memory needs to be recycled” However, the determination of this problem in the program means that it can not be accurately and completely solved by a certain algorithm. The recovery mechanism discussed later can only solve the general problem in a limited way.

Recovery algorithm

The problem of whether or not garbage collection needs to be recycled mainly depends on whether the variable can be accessed or not

  • Mark cleanup
  • Reference count

Mark cleanup

Tag cleaning is the most commonly used recycling strategy for JS, which has been used by all browsers since 2012. Since then, the improvement of the recycling strategy is also based on the improvement of this strategy. The strategy is as follows:

  1. When a variable enters a context, it can also be understood as a scope. It will be marked to prove that it exists in the context;
  2. Remove all the variables in the context and the variables referenced in the context, indicating that these variables are active and useful;
  3. After that, the marked variables are marked as the variables to be deleted, because the variables in the context can no longer access them;
  4. Perform memory cleaning, destroy all marked inactive values and reclaim the previously occupied memory;

Let's look at JavaScript's garbage collection mechanism

limit
  • Since the search starts from the root object (global object), objects that cannot be queried from the root object will be cleared
  • After recycling, memory fragments will be formed, affecting the subsequent application of large continuous memory space

Reference count

The reference counting strategy is not commonly used because of its many disadvantages. The idea is to record the number of times it is referenced for each value, and determine whether to keep it by judging the number of times (the number of references is 0). The specific rules are as follows

  • When you declare a variable and assign it a reference value, count + 1;
  • Reference + 1 when the same value is assigned to another variable;
  • The variable saving the reference to the value is overridden by other values, reference – 1;
  • If the reference is 0, reclaim the memory;
limit

The most important question is,Circular referenceThe problem of

function refProblem () {
    let a = new Object();
    let b = new Object();
    a.c = b;
    b. C = a; // cross reference
}

According to the rules mentioned earlier, both of them refer to each other, and the reference count is not 0, so neither variable can be recycled. If the function is called frequently, it will cause a very serious memory leak.

Nodejs V8 recycling mechanism

The recovery mechanism of V8 is based onGenerational recycling mechanismMemory is divided into young generation and tenured generation. The new generation is the object with shorter survival time, and the older generation is the variable with longer survival time or memory resident.

Let's look at JavaScript's garbage collection mechanism

Composition of V8 heap

V8 divides the heap into several different regions

Let's look at JavaScript's garbage collection mechanism

  • New space / young generationMost of the new objects are allocated to this area and are divided into two spaces, which occupy a small space as a whole. The frequency of garbage collection is high. The recycling algorithm isScavengealgorithm
  • Old space / old generation: most of the objects that have survived in the new area for a period of time will be transferred here. The recovery algorithm isMark sweep & Mark compact (major GC)The interior is subdivided into two spaces

    • Old pointer space: the stored object contains pointers to other objects
    • Old data space: the stored object contains only data and has no pointers to other objects
  • Large object space: holds large objects that exceed the limits of other spaces, and the garbage collector never moves objects in this space
  • Code space: code object, used to store code segments, is the only memory space with execution permission. It should be noted that if the code object is too large to be moved into the large object space, the code object also has execution permission in the large object space, but it can not be said that the large object space also has execution permission
  • Cell, property, map space: these areas store cell, attribute cell and map. Since each space stores elements of the same size, the memory structure is very simple.

Scavenge algorithm

Scavenge algorithm is the main algorithm in the new generation space. This algorithm was written by C.J. Cheney in 1970A nonrecursive list compacting algorithmProposed.
Scavenge mainly adoptsCheney algorithmThe heap memory of the new generation space of Cheney algorithm is divided into two spaces of the same size, called semi space. The in use state is called from space, and the idle space is called to space. The recycling process is as follows:

  • Check the from space. If the from space is full, the scavenge algorithm is executed for garbage collection
  • If the allocation is not full, check whether there is a live object in the from space. If there is no live object, the space of the non living object will be released directly
  • If it survives, it will check whether the object meets the promotion conditions. If it meets the promotion conditions, it will be moved into the old generation space. Otherwise, the object will be copied into the to space
  • After copying, swap the roles of from and to spaces, and then start from step 1
Promotion conditions
  1. Experienced scavenge algorithm screening once;
  2. More than 25% of to space is used;

Let's look at JavaScript's garbage collection mechanism

Mark sweep & Mark compact (major GC) algorithm

As mentioned before, mark clean policy will produce memory fragmentation, which will affect the use of memory. Here, the emergence of mark compact algorithm can solve this problem very well. Mark sorting algorithm is based on mark sweep, which moves active objects to the boundary, and then clears inactive objects.

Let's look at JavaScript's garbage collection mechanism

Because the moving objects need to be moved, the processing speed is slower than mark sweep.

Stop the world

In order to avoid the difference between the application logic and the logic seen by the garbage collector, the garbage collector will stop the application logic when performing the collection task, and then continue to execute the application logic after completing the collection task. This kind of behavior isTotal pauseThe pause time depends on the time it takes for different engines to perform a garbage collection. This kind of pause has little influence on the space of Cenozoic, but it may cause pause to the space of old generation.

Incremental marking

In order to solve the phenomenon of total pause, V8 introduced incremental marking in 2011. V8 divides the marking process into sub marking processes one by one. At the same time, the garbage collection tag and JS application logic are alternately carried out until the tag is completed.

Let's look at JavaScript's garbage collection mechanism

Memory leak

Memory leaks are hard to detect and can be a big problem when functions are called many times. The common memory leaks include the following scenarios.

Unexpected declaration of global variables
function hello (){
    name = 'tom'
}
hello();

Undeclared objects will be bound to global objects. Even if they are not used, they will not be recycled. Therefore, when you write code, you must remember to declare variables.

timer
let name = 'Tom';
setInterval(() => {
  console.log(name);
}, 100);

The callback of the timer refers to external variables through the closure. If the timer is not cleared, name will always occupy the memory. Therefore, when using the timer, it is better to know what variables you need and check the internal variables of the timer. In addition, if you do not use a timer, remember to clear the timer in time.

closure
let out = function() {
  let name = 'Tom';
  return function () {
    console.log(name);
  }
}

Since closures will reside in memory, in this example, if out always exists, name will not be cleaned. If the value of name is large, it will cause a serious memory leak. So be careful with closures.

event listeners
mounted() {
window.addEventListener("resize",  () => {
    //do something
});
}

Event monitoring is bound when the page is initialized, but it is not cleared when the page leaves, which will lead to memory leakage.

last

This article is a summary of the reference material. I have been studying JS again recently. I will record the review summary in GitHub,Poke this, if you want to review together, you can participate in the review and summary together!

reference material
  1. significant Node.js Memory leak problem
  2. JS garbage collection mechanism
  3. A tour of V8: Garbage Collection
  4. JS exploration – GC garbage collection
  5. JavaScript memory management
  6. JavaScript advanced programming (4th Edition)