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