JS garbage collection mechanism and memory leak

1. Browser memory leak

The V8 engine encapsulated by the browser supports parsing of JS. When the program is running (runtime), as long as the program requires memory, such as when declaring variables such as assigned strings, objects, and arrays, the operating system must allocate memory for use. Variables of the running service process are constantly increasing, and the memory is not released in time, the memory occupancy will become larger and larger, which will affect the performance of the system, or directly cause the system to crash.

1. Closure and reference

    let fn = () =>{
    
    
        let a = 0
        return () => {
    
    
            return a++
        }
    }

    let b = fn()
    console.log(b())    // 0
    console.log(b())    // 1

Closures can cause memory leaks under IE6, but they are no longer considered. Although the variable a cannot be recycled (equivalent to a global variable), there is no special consideration for this memory. It is worth noting that the closure itself does not cause memory leaks, but too many closures can easily lead to memory leaks

2. Mutual references

let aa = {
    
    }
let bb = {
    
    }
aa.c = bb
bb.c = aa

Solution: Do not refer to variables

3. Global undeclared variables

    function fn1() {
    
    
        aa = 1  //  window.aa
        console.log(aa)
    }
    fn2()

    function fn2() {
    
    
        this.bb = 1 //  window.bb
        console.log(bb)
    }
    fn2()

The functions fn1 and fn2 are not declared, that is, the variables are bound to the global object window, so that the variable memory cannot be released after the function is executed.
Solution: Use strict mode and add'use strict' to the top of js

4. Timer and callback function

    let a = 2
    setInterval(() =>{
    
    
        console.log(a++)
    }, 1000)

When setInterval or setTimeout is not needed, the timer is not cleared, and the timer's callback function and internal dependent variables cannot be recycled, causing memory leaks.

5. Add attributes to the DOM object

document.getElementById('id')[property] = obj

If the DOM exists, it will always bind this event. The solution is as follows:

window.onunload = function(){
    
    
  document.getElementById('id')[property] = null
}

7. Timer, event monitoring, $on, etc. in vue.
Solution: remove or close related events in the beforeDestroy hook

Two, garbage collection mechanism

Variable life cycle: when a variable's life cycle ends, the memory pointed to by it should be released. JS has two kinds of variables, global variables and local variables generated in functions (not including referenced variables). The life cycle of local variables ends after the function is executed, and the memory it references can be released (that is, garbage collected), but the life cycle of global variables will continue until the browser closes the page. The garbage collector will detect variables that are no longer in use, and then release the memory occupied by them, and execute them periodically at a fixed time interval

There are two main types of garbage collection mechanisms in modern browsers: mark removal and reference counting.
1. Mark-and-sweep The
current mainstream IE, Firefox, Opera, Chrome and Safari browsers all use the mark-and-sweep garbage collection strategy.
How it works: When a variable enters the environment, the variable is marked as "enter environment". When a variable leaves the environment, it is marked as "out of the environment". The memory marked "Leave the environment" is reclaimed.

Work flow:
1. Garbage collector will mark all variables stored in memory when it is running.
2. Remove the global variables and the tags of the variables referenced by the variables in the environment.
3. The marked will be regarded as the variable to be deleted.
4. The garbage collector completes the memory cleanup, destroys the marked values ​​and reclaims the memory space they occupy.

2. Reference counting (reference counting)
The meaning of reference counting is to track and record the number of times each value is referenced. When a variable is declared and a reference type value is assigned to the variable, the number of references to this value is 1. If the same value is assigned to another variable, the number of references to the value is increased by 1. On the contrary, if the variable that contains the reference to this value gets another value, the number of references to this value is reduced by 1. When the number of references to this value is 0, it means that there is no way to access this value anymore, so you can Reclaim the memory space it occupied.

let aa = []   // 数组[]引用1次
let bb = aa  //  数组引用2次
bb = null  //  释放内存,引用还剩下1次,即变量aa的引用还存在

Such a simple garbage collection mechanism is very prone to circular reference problems, which may cause memory not to be recycled and cause memory leaks; for example:
let aa = {}
let bb = {}
aa.c = bb
bb.c = aa

var wraper = document.querySelector('#btn');
wraper.onclick = handle;
wraper = null;

wraper = null;
This method cannot release the dom click event, because the variable referenced by the wraper is released, and the actual object DOM has already bound the btn click event, for example

  let a = {
    
    }
    let b = a
    b.btn = () =>{
    
    }
    b = null
    console.log(a)

Guess you like

Origin blog.csdn.net/zxlong020/article/details/108566610