This is the 9th day of my participation in the August More Text Challenge

Introduction to Performance Optimization

  • Performance optimization is inevitable
  • What can be considered performance optimization
  • Ubiquitous performance optimization

Memory management

Why is memory managed

function fn(){
    arrList = []
    arrList[10000] = 'lg is a coder'
}
fn()
// Causes a memory leak
Copy the code

Introduction to Memory Management

  • Memory: It consists of read and write units and represents a piece of operable space
  • Management: the artificial manipulation of the application, use and release of a space
  • Memory management: developers actively apply for space, use space, release space
  • Management process: apply – use – release

Memory management in JavaScript

  • Applying for Memory Space
  • Used memory space
  • Free up memory

Garbage collection in JavaScript

  • Memory management in JavaScript is automatic
  • Objects are garbage when they are no longer referenced
  • Objects that cannot be accessed from the root are garbage

Reachable objects in JavaScript

  • Objects that can be accessed are reachable objects (by specific reference, or by scope chain in the current context)
  • The criterion of reachability is whether it can be found from the root
  • The root in JavaScript can be understood as a global variable object (global execution context)

References and reachability in JavaScript

//obj and name are reachable
let obj = { name: 'xm' }
// the reference to obj is set to +1
let ali = obj 
// Because ali's reference to name is still reachable
obj = null

console.log(obj)
console.log(ali)
//null
//{name:'xm'}
Copy the code
function objGroup(obj1, obj2) {
    obj1.next = obj2
    obj2.pre = obj1
    return {
        o1: obj1,
        o2: obj2
    }
}
const obj = objGroup({ name: 'obj1' }, { name: 'obj2' })
console.log(obj)

/ / {
// o1: 
      
        {
      
// name: 'obj1',
// next: { name: 'obj2', pre: [Circular *1] }
/ /},
// o2: 
      
        {
      
// name: 'obj2',
// pre: 
      
        { name: 'obj1', next: [Circular *2] }
      
/ /}
// }
Copy the code

GC algorithm

GC definitions and functions

  • Garbage Collection (GC) is shorthand for Garbage Collection mechanism
  • GC finds garbage in memory and frees and reclaims space for subsequent use of code

What is the garbage in the GC

  • Objects that are no longer needed in a program
function func(){
    name = 'lg'
    return `${name} is a coder`
}
func()
Copy the code
  • An object in a program that can no longer be accessed
function func(){
    const name = 'lg'
    return `${name} is a coder`
}
func()
Copy the code

What is the GC algorithm

  • The GC is a mechanism by which the garbage collector does the specific collection
  • The job is to find garbage, free space, reclaim space
  • An algorithm is a set of rules that lookup and recycle follow at work

Common GC algorithms

  • Reference counting
  • Mark clearly
  • Tag to sort out
  • Generational recycling

Reference counting algorithm

  • Core idea: Set the number of references to determine whether the current number of references is 0
  • Reference counter
  • Modify the reference number when the reference relationship changes
  • Reclaim immediately if the reference number is 0

Advantages of reference counting algorithms

  • Recycle rubbish as soon as it is found
  • Minimize program pauses

Disadvantages of the reference counting algorithm

  • Object referenced by loop cannot be recycled
  • Time overhead (always monitoring the reference count of each object)
// Circular reference
function fn(){
    const obj1 = {}
    const obj2 ={}
    Obj1 and obj2 in the fn function are declared inside the function, but there are circular references between them. The reference counting algorithm cannot reclaim their space
    obj1.name = obj2
    obj2.name = obj1
    return 'lg is a coder'
}

fn()
Copy the code

The realization principle of tag clearing algorithm

  • Core idea: mark and clear two stages to complete
  • Traverse all objects to find and mark all active objects (also reachable objects), and recursively find child nodes and child nodes
  • Iterate through all the objects and clean up the unmarked objects, and remove the previously marked objects so that the GC can work again next time
  • Reclaim the corresponding space and give it to the free list

Advantages and disadvantages of the tag clearing algorithm

  • Address the disadvantages of object operation cyclic references as opposed to reference counting

Disadvantages of the tag clearing algorithm

  • Address discontinuity, space fragmentation, recycling garbage on the address discontinuity, not conducive to the maximum use of space
  • Garbage objects are not collected immediately, and the current program stops working while garbage is collected

Principle of tag collation algorithm

  • Tag cleanup can be seen as an enhancement to tag cleanup
  • The operation of the tag phase is the same as that of tag clearing
  • The cleanup phase starts with a cleanup, moving the object so that the reclaimed space is contiguous at the address

  • Reduce the space for fragmentation
  • Garbage is not collected immediately

V8 engine

  • V8 is a mainstream JavaScript execution engine (Node, Chrom)
  • V8 uses just-in-time compilation: whereas previous engines turned code into bytecode, V8 turned code into machine code that can be run directly, so it can be very fast
  • V8 memory has an upper limit: Upper limit of 64 – bit operating system is not more than 1.5 G, 32-bit operating system, no more than 800 m because V8 itself is built for the browser to the existing memory size is enough, for web use V8 marks using incremental algorithm of recycling 1.5 gb of memory will only consume 50 ms, the incremental tag way of recycling the need to consume 1 s, so by a 1 s

V8 garbage collection strategy

  • The idea of generation recycling is adopted
  • Memory is divided into new generation, old generation
  • Different algorithms are used for different objects

How does V8 recycle new generation objects

  • V8 memory space is split in two
  • Little space to store the new generation object (32 m | 16 m)
  • A new generation is an object that has a short shelf life (e.g., a variable in a local scope)

New generation object recovery implementation

  • The recycling process adopts replication algorithm + label finishing
  • The new generation of memory is divided into two equally large Spaces
  • The usage state is From space and the free space is to state
  • Live objects are stored in the From space, and when the From space is used to a certain extent, GC operations will be triggered to clean up the mark and make the position continuous to ensure that there will be no fragmented space later
  • The active objects will be copied To the To space after the markup is collated. The objects in the From space will have a backup in the To space, so the From space can be recycled and the From space can be freed
  • From and To swap space To complete the release

Recovery Details

  • Promotion may occur during copying, if the space used by a variable object is also present in the old generation object
  • Promotion is moving new generation objects to old generation for storage
  • A new generation of GC that is still alive needs to be promoted to the old generation
  • As the usage of To space exceeds 25%, objects need To be moved To the old generation for storage, because when the To space reaches a certain range and is exchanged with From, the space used by new objects will be insufficient.

How does V8 recycle old generation objects

  • Old age objects are stored in the old age area on the right
  • 64-bit operating systems have 1.4 GB of space and 32-bit operating systems have 700 MB
  • Aged objects are objects that have a long lifetime (global variables, and closures)

Old age recycling implementation

  • It mainly adopts the algorithm of mark clearing, mark finishing and increment mark
  • Firstly, mark clearing is used to complete the release and recycling of garbage space, and all active objects of the old generation are found to mark, and then the space of garbage objects is released. In this way, the problem of space debris exists. Compared with space debris, its promotion speed is relatively obvious
  • Space, using tags to sort out: when a new generation of object will be moved to the old generation, and the time of the old generation storage space is not enough to store new generation move over the object that would trigger the tag, the fragments of the space before recycling, there will be more space to use
  • Incremental marking is used for efficiency optimization

Details of the contrast

  • New generation of regional garbage recycling use space for time
  • Old generation area reclamation is not suitable for replication algorithm

How do tag deltas optimize garbage collection

When garbage collection, it will block the execution of our program. The marked increment is to divide the whole garbage collection into several small parts to complete the whole collection, so as to replace the garbage collection operation done in one go before, mainly to realize the garbage collection and program execution alternately

The V8 engine does not take more than 1s to handle a maximum 1.5 gigabytes of garbage collection using non-incremental tags

JavaScript code optimization

How to accurately test JavaScript performance

  • Log in using your GitHub account
  • Personal Information (optional)
  • Fill in detailed test case information (title, SLug)
  • Fill in the prep code (often used in DOM manipulation)
  • Setup and teardown are required
  • Fill in the test snippet

Be careful with global variables

Why should it be used sparingly?

  • Where clustering variables are defined in the global execution context, which is the top of all scope chains and takes a lot of time to find
  • The global execution context remains in the context execution stack until the program exits, which is detrimental to GC work and reduces memory usage during program execution
  • The presence of a variable with the same name in a local scope can obscure or contaminate the whole world
1 / / method
var i, str = ' '
for (i = 0; i < 1000; i++) {
    str += i
}
2 / / method
for (let i = 0; i < 1000; i++) {
    let str = ' '
    str += i
}
Copy the code

Caching global variables

Global variables that cannot be avoided in use are cached locally

        function getBtn(){
            let btn1 = document.getElementById('btn1')
            let btn3 = document.getElementById('btn3')
            let btn5 = document.getElementById('btn5')
            let btn7 = document.getElementById('btn7')
            let btn9 = document.getElementById('btn9')}function getBtn2(){
            let obj = document
            let btn1 = obj.getElementById('btn1')
            let btn3 = obj.getElementById('btn3')
            let btn5 = obj.getElementById('btn5')
            let btn7 = obj.getElementById('btn7')
            let btn9 = obj.getElementById('btn9')}Copy the code

Add by prototype

Methods needed to add an instance object to a prototype object

1 / / way
var fn1 = function () {
    this.foo = function () {
        console.log(111)}}let f1 = new fn1()

// Mode 2-- This mode performs better
var fn2 = function () { }
fn2.prototype.foo = function () {
    console.log(111)}let f2 = new fn2()
Copy the code

Avoid closure traps

Closure features

  • The outside has a reference to the inside
  • Access data from the inner scope in the outer scope
function foo(){
    var name = "lg"
    function fn(){
        console.log(name)
    }
    return fn
}
var a = foo()
a()
Copy the code

About the closure

  • Closures are a powerful syntax
  • Closures are prone to memory leaks when used improperly
  • Don’t close for closure’s sake
<button id="btn1">add</button>
        <script>
        /* Memory performance optimization */
        function foo(){
            * * Currently memory is leaking because references to EL exist in the Dom reference code, so GC does not reclaim el */
            var el = document.getElementById('btn1')
            el.onclick=function(){
                console.log(el.id)
            }
        }
        foo()

        function foo(){
            var el = document.getElementById('btn1')
            el.onclick=function(){
                console.log(el.id)
            }
            // Resolve memory leaks
            el=null
        }
    </script>
Copy the code

Avoid attribute access methods

Object orientation in JavaScript

  • Js does not require access to properties, all properties are externally visible
  • Using attribute access methods only adds another layer of redefinition without access control
1 / / method
function Person(){
    this.name = "icoder"
    this.age = 18
    this.getAge = function(){
        return this.age
    }
}

const p1 = new Person()
const a = p1.getAge()


2 / / method
function Person(){
    this.name = "icoder"
    this.age = 18
}

const p1 = new Person()
const a = p1.age

// Method 2 performs better
Copy the code

For loop optimization

<button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <button class="btn"></button>
        <script>
        let btns = document.getElementsByClassName("btn")

        for(var i =0; i<btns.length; i++){console.log(i)
        }
// The second method has better performance and saves money
        for(var i =0,len = btns.length; i<len; i++){console.log(i)
        }
Copy the code

The optimal cycle is adopted

//forEach performs best
let arr = new Array(1.3.4.5.6)
arr.forEach((item) = > {
    console.log(item,'foreach')})for (var i = arr.length-1; i>-1; i--) {
    console.log(arr[i],'for')}for(let i in arr){
    console.log(arr[i],"in")}Copy the code