Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Memory control
JavaScript implements automatic memory management through garbage collection, eliminating the need for developers to focus on allocating and freeing memory during code writing as C/C++ does.
When developing in a browser, very few people encounter a situation where garbage collection has a performance impact on an application.
Node greatly expands the application scenario of JavaScript. When the mainstream application scenario extends from the client side to the server side, it can be found that, for the performance sensitive server program, good memory management, good garbage collection status, will affect the service.
Why focus on memory
- Prevent pages from occupying too much memory, resulting in client lag, or even no response (browser)
- Node also uses V8, and memory is critical to the performance of back-end services. Because of the persistence of the service, the back end is prone to memory overflow
The Node with the V8
In Node, this is all tied to Node’s JavaScript execution engine V8. Node.js is a JavaScript runtime based on the Chrome V8 engine
When Ryan Dahl, the founder of Node, chose V8 as the JavaScript engine for Node, it was because of the third browser war, in which Chrome’s JavaScript engine V8 became the focus of outstanding performance, and V8 continued to lead in the following performance scores. I used to write about Internet Explorer in times Have Changed?! The third major battle ended with Chrome’s victory.
V8 engine
The V8 engine was developed by Lars Bak, and the first version was released along with the first version of Chrome on September 2, 2008.
Lars Bak’s track record was largely virtual machine related, focusing on the development of high performance Java virtual machines, which helped V8 surpass all JavaScript virtual machines at the time.
The V8 engine is written in C++.
V8 engine garbage collection mechanism:
- V8’s memory allocation is divided into heap and stack
- Stack memory stores basic type data as well as memory addresses that reference type data
- Heap memory stores reference type data
- Garbage recycling mainly exists in the new generation and old generation of heap
- There are two Spaces in the Cenozoic,
Semi space from
andSemi space To
The two Spaces are divided in strict half - Old generation: passed at least two rounds from Cenozoic space
Minor GC
Data that still survives - Memory size depends on the operating system,
A 64 - bit
is1.4 G
.32 -
is0.7 G
- 64 Cenozoic space is
64MB
, old boy1400MB
- 32 Cenozoic space is
32MB
, old boy700MB
- New Versions of Node have 2 gigabytes of memory since V14
- 64 Cenozoic space is
- The new generation and the old generation are using two completely different recycling mechanisms
- The new generation
Scavenge
Algorithms (New generation interchange) - Old generation is mark finishing and clearing:
Mark-Sweep
(Mark cleared),Mark-Compact
(Mark finishing) - Reference link: blog.csdn.net/weixin_3998…
- The new generation
graph RL; Subgraph Heap memory subgraph New space n[" is where the newly generated data lives, These data are often transient. "] subgraph Semi space from in use end\ subgraph Semi space To in idle state end end subgraph Old space O subgraph Old Pointer space o1[" If an object has a pointer reference or points to another object, End subgraph Old data space O2 [" If an object is a primitive object with no pointer reference, Data space"] end end subgraph Large object space d[" Large object space is not processed by gc "]-->d1[" Then the object will be placed in the large object space. "] end subgraph Code space d3[jIT-compiled Code space] --> The only executable space other than allocating and executing Code in the large object space Stack memory stores the base type data and the memory address that references the type data end end
The new generationScavenge
algorithm
The new generation stores objects with a short life cycle, and allocating memory is easy. It only stores a pointer to the memory space and increments the pointer according to the size of the allocated object. When the storage space is nearly full, a garbage collection is performed
As mentioned earlier, the Cenozoic is divided into two Spaces, Semi space from used state space and Semi space To idle state space.
Garbage collection process:
- When three variables A, B, and C are defined, the
from
Store using the open location in the state space.
- when
from
When the space is about to be full, judge garbage collection and find that B is not referenced by other, it can be recycled and mark B
- Copy unmarked A and C to
To
In idle space
- remove
from
Everything in space
- will
from
Space andto
Switched spatial identities, switched post-switchedfrom
There’s A and C in space, and B disappears.to
The space is still empty.
This is the recycling process of the new generation, and the Scavenge avenge is a typical space-for-time algorithm, so it can’t be applied on a large scale to all garbage recycling
Advantage: Scavenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Avenge Disadvantages of the Scavenge avenge: Use only half of the heap memory, as dictated by the space partitioning and replication mechanisms.
Writing barrier tips:
- How can I tell if an object is active if only one pointer points to it and the pointer is in the old generation space when GC traverses the new generation to mark it?
- It’s inefficient to iterate over old objects
- There is actually a list in the write buffer (we call it
CrossRefList
), which records all old zone objects pointing to the new zone- When there is a pointer to an object in the old block that points to an object in the new block, we record such a cross-block pointer
- Newly generated objects are not recorded
- This recording behavior always occurs during a write operation. It is called a write barrier, and a write barrier occurs for every write operation
- When the New generation GC encounters such an object, it goes back and reads the record list
The new generation rose to the old generation
- When an object survives more than two copies, it is considered a long-lived object.
- And once the memory space of the new generation exceeds the occupancy threshold, such objects with a long life cycle will be moved to the old generation and managed by a new algorithm.
Old generation mark sorting and clearing
The older generation can’t be used the way the newer generation can because of the large amount of memory and the amount of objects stored.
The reason:
- Half of the space is too waste of space, old generation of space is much larger than the new generation, waste will be very serious
- If there are too many live objects, the efficiency of copying live objects is low
The Mark-sweep flag clears
Mark mark-sweep icon:
Step 1: mark. Start from a set of root elements, traverse this group of root elements in breadth and recursively. In this traversal process, the elements that can be reached are active objects, and the elements that cannot be reached can be judged as inactive objects, that is, junk data, and mark inactive objects. Step 2: The gray part is the data to be collected marked before garbage collection, and the gray part is cleared after garbage collection.
Mask-compact markup collation
However, this method generates a large amount of memory fragmentation, which can lead to insufficient memory if an object needs a large contiguous chunk of memory.
The second mask-compact algorithm is needed.
The steps for marking are the same, except that instead of directly cleaning up the garbage, you move all surviving objects to one end and then directly clean up the memory beyond that end
While mask-Compact markup consolidation looks cleaner and more space-efficient than markup clearance, in older generations it was a combination of the two, and because Mark-Conpact required moving objects, it was not fast
Tricolor marking
Three colors as follows:
- White: Unmarked objects, i.e. unreachable objects (objects not scanned), can be collected
- Gray: An object that has been marked (reachable object) but has not been scanned and cannot be collected
- Black: has been scanned (reachable object, live object) and is not recyclable
Refer to the article: blog.csdn.net/star1210644…
Cleaning efficiency
The pause
Since garbage collection is performed in the JS engine, and the Mark-Compact algorithm needs to move objects during execution, it cannot execute very fast when there are many live objects. To avoid inconsistencies caused by competing memory resources between the JavaScript application logic and the garbage collector, The garbage collector pauses the JavaScript application, a process known as stop-the-world.
This is also caused by JavaScript being single threaded. JavaScript runs on the main thread and garbage collection causes JavaScript to stop running.
For the new generation, total pause has little impact on the efficiency, but in the old generation, because there are many active objects, it takes a long time to sort out and clear marks, and total pause has a great impact on the efficiency, which will suspend the main thread for a long time, making the page become stagnant.
The V8 engine uses incremental tagging, parallel collection, and concurrent collection to replace total pauses.
Here are some optimization techniques for reference:
- Blog.csdn.net/weixin_3440…
- www.cnblogs.com/cangqinglan…
Interview questions:
- Why tidy up?
- Token clearing alone can create a lot of fragmented space, and errors can occur if the contiguity of memory required by the object is large
- Why is the mark finishing method cleaned first?
- Part of the mark objects will be overwritten by the active objects in the collation process, and the mark objects that need to be cleared at one time can be reduced in the later clearing process, reducing the space complexity
Web rendering process
Node directly benefits from V8 in JavaScript execution and can benefit from new language features (ES6) as V8 upgrades, but it is also subject to some of V8’s limitations.
V8 memory limits
In a normal back-end development language, there is no limit to the basic memory usage, whereas in Node, using memory through JavaScript can only be partially used.
Reasons for limiting heap size for V8
- V8 was originally designed for browsers, and there was no reason to use a lot of memory
- The limitations of V8 garbage collection mechanism. Taking 1.5g garbage collection heap memory as an example, V8 takes more than 50 milliseconds to do a small garbage collection, and even more than 1 second to do a non-incremental garbage collection
- Memory limits can be manually adjusted for Node use
--max-old-space-size
or--max-new-space-size
You can adjust the size of the memory limit