Introduction to the

V8 engine is a JavaScript engine implementation originally designed by some language experts, acquired by Google, and subsequently open-source by Google. V8 is developed in C++ and compiles it to native machine code (ia-32, x86-64, ARM, or MIPS CPUs) before running JavaScript, compared to other JavaScript engines that convert it to bytecode or interpreted execution. Methods such as inline caching are used to improve performance. With these features, JavaScript programs run as fast as binary programs in V8. V8 supports many operating systems, such as Windows, Linux, Android, etc., and other hardware architectures, such as IA32,X64,ARM, etc., with good portability and cross-platform features. Both Chorme and Node.js use v8 engines.

Memory management

The memory space of javascript is divided into Heap and Stack. A heap is an array of tree structures. A stack is an array structure that follows a “first in, last out” principle

The stack

A stack is a temporary variable storage space that stores local variables and function calls in javascript.

Variables of basic data types are stored directly on the stack, such as String, Number, Boolean, Null, Undefined, Symbol, and so on. Complex type data stores the reference to the object (the actual stored pointer address) on the stack, and the data itself is stored in the heap.

Each time a function is called, the JS interpreter creates a call stack in the stack to store the order in which the function is called. The function is then added to the call Stack, and the interpreter creates a Stack Frame for the added function. This Stack Frame holds the local variables of the function and executes the statement immediately. If the executing function also calls other functions, the new function will be added to the call stack and executed. When this function completes, the corresponding stack frame is destroyed immediately.

The heap

The heap is used to store complex data objects. It is also divided into code space, Map space, Large object space, New space, old space and so on.

Memory formation

In Chrome, when JS is running, memory generally consists of the following parts:

  • Code Space
  • Map space
  • Large Object Space
  • New Space
  • Old Space

Code Space

Store precompiled code.

Map space

Stores the Map information of an object. Each Map object has a fixed size, so this space is separated out for quick positioning.

Large object space,

To avoid copying large objects, use this space exclusively to store large objects. This includes Code, FixedArray, and more.

New Space

Most objects are stored in this area when they are created. It is mainly composed of two semispace(half space), from area and to area. The maximum memory is 32MB and 16MB on 64-bit and 32-bit systems, respectively. Scavenge algorithm is used in the recycling process of the new generation.

Objects are assigned to the FROM region when they are created, and in the Garbage Collection phase, surviving data from the FROM region is copied to the TO region and then interacted with the TO and FROM regions. Implement a garbage collection. Data that survives both GCS is moved to the old generation region for storage.

The Cenozoic GC has high frequency and fast speed, but the space utilization rate is low, which is a typical way of space for time.

Data promotion in the new generation

When an object survives multiple (two) copies, it is considered a long-lived object and is moved directly to the old generation at the next garbage collection. This process of moving objects from the new generation to the old generation is called promotion.

Data promotion in the new generation requires either of the following two conditions:

  1. The object is Scavenge and, if so, put in older data
  2. Is the remaining memory of the to area less than 25%? If so, put it into the old generation

Old Space

Objects from the Cenozoic generation that are still alive after repeated recycling are transferred to older generations with more space. Because the old generation space is large, if Scanvage algorithm is still used to copy objects frequently, the performance overhead is very high, and it is not suitable for this scenario.

Today, in the old generation, “Mark-sweep” is mostly used for GC. In the past, “reference counting” was used for GC, but this method is prone to memory leakage, mainly in the case of circular reference, data cannot be recycled normally, resulting in memory surge, resulting in memory leakage.

Mark-sweep is divided into two main stages: marking and cleaning.

Mark phase

In the marking phase, all objects in the heap are iterated, and the living objects are marked. The Sweep algorithm mainly determines whether an object can be accessed and then knows whether the object should be reclaimed. The specific steps are as follows:

  1. The garbage collector internally builds a root list of variables that can be accessed from the root node. In JavaScript, for example, the Window global object can be treated as a root node.

  2. The garbage collector starts from all the root nodes, walks through the child nodes it can access and marks them as active. Places that the root node cannot reach are inactive and will be considered garbage.

Sweep phase

This stage is to clean up the variables that cannot be accessed in the marking stage.

Mark – Sweep optimization

Mark – Sweep algorithm is a problem, it is, after experienced a Mark clear memory space may appear discontinuous state, because we have to clear the memory address of the object may not be continuous, so the fragments of memory will appear problem, cause behind if a large object you need to allocate and free memory to allocate, The garbage collection is triggered prematurely, which is unnecessary because we do have a lot of free memory, but it’s not contiguous.

In order to solve this problem, the mark-Compact algorithm is proposed to solve the problem of memory fragmentation. The algorithm is mainly used to solve the problem of memory fragmentation. After the dead objects are cleared in the reclamation process, the live objects are moved to the other end of the heap during the defragmentation process. After the move is complete, clean up all memory outside the boundary.

Incremental Marking

Due to the single thread mechanism of JS, the garbage collection process will hinder the execution of the same step task of the main program. After the garbage collection is completed, the logic of executing the main task will be resumed again. This behavior is called stop-the-world. The marking phase also blocks the execution of the main thread. Generally speaking, the old generation will hold a large number of living objects, and if the entire heap is traversed during the marking phase, it will cause serious lag. Therefore, to reduce the pause time caused by garbage collection, V8 introduced Incremental Marking, in which a portion of objects in the heap are marked and then paused, handing execution back to the JS main thread. Wait until the main thread task is finished and then continue marking from the original pause mark until the whole heap is marked. This concept is similar to the Fiber architecture in the React framework. Only when the browser is idle, it will traverse the Fiber Tree to execute corresponding tasks. Otherwise, the execution will be delayed to minimize the impact on the main thread, avoid application lag, and improve application performance.

Thanks to incremental tagging, the V8 engine went on to introduce lazy sweeps and incremental compaction to make cleaning and recompaction happen incrementally. In order to make full use of the performance of multi-core CPU, parallel marking and parallel cleaning will also be introduced to further reduce the impact of garbage collection on the main thread and improve the performance of the application.

reference

  • Blog.csdn.net/qq_29438877…
  • www.cnblogs.com/cangqinglan…
  • V8. Dev/blog/concur…