1. JavaScript memory management

Low-level languages like C typically have low-level memory management interfaces, such as malloc() and free().

Instead, JavaScript allocates memory automatically when variables (objects, strings, etc.) are created, and “automatically” frees them when they are not used.

The process of release is called garbage collection. This “automation” is a source of confusion and gives JavaScript (and other high-level languages) developers the false sense that they can afford not to care about memory management.

The memory life cycle is basically the same regardless of the language: 1. Allocate the memory you need 2. Use the allocated memory to read/write. 3. Reclaim/release the memory when it is no longer needed

All languages are explicit in part II. The first and third parts are explicit in low-level languages, but most of them are implicit in high-level languages like JavaScript.

2. Why do we need garbage collection

Because strings, objects, and arrays have no fixed sizes, they can only be allocated dynamically when their sizes are known. Every time a JavaScript program creates a string, array, or object, the interpreter must allocate memory to store that entity. Whenever memory is allocated dynamically like this, it must eventually be freed so that it can be reused, otherwise the JavaScript interpreter will consume all available memory in the system, causing the system to crash.

In a word: limited memory, unlimited demand

Chrome’s garbage collection algorithm

Let’s start with the general flow of objects during GC: objects are stored in the nursery area of the new generation region when they are first declared, objects that survive the first GC are moved to the Intermediate region, and objects that survive the second GC are moved to the old generation region if they are still alive.

How does the browser tell if an object should be deleted or kept? This is based on the reachability of the current variable to the root node.

Conclusion:

Objects with a short life span belong to the Cenozoic era.

Objects that live for a long time belong to old generation.

Active object: the root node is reachable

Non-live objects: unreachable by the root

Let’s start with the details.

3.1 New generation garbage collector

In javascript, the memory allocated by any object declaration will be placed in the new generation first, and since most objects live in memory for a short period of time, a very efficient algorithm is required.

  • The New generation uses the scavenge algorithm for recycling

Scavenge is a replication algorithm. It will copy the current region A to region B, then clean up the inactive objects in region B and sort them, and then assign A = B

  • Cenozoic areas typically have only 1-8MB of space.

  • Object promotion phenomenon

Objects that survive each GC are promoted until they move to the nursery -> intermediate -> nursery – generation region

3.2 Legacy garbage collector

Objects in Cenozoic space will be transferred to old age area after meeting certain conditions. The old generation used mark-sweep and Mark-Compact algorithms for garbage collection.

3.2.1 Mark-sweep algorithm

Mark-sweep processing is divided into two stages, marking stage and cleaning stage. In the old generation, live objects accounted for the majority, so Mark-sweep immediately cleared the inactive objects after marking the active and inactive objects.

  • Marking stage: The first scan of the old generation is carried out to mark active objects
  • Cleaning stage: The old generation is scanned for the second time to clear the unmarked objects, that is, to clean the inactive objects

The memory itself is a continuous storage space. After being marked, the memory will become discontinuous, and the cleared objects are all over the memory address, resulting in a lot of memory fragments. Hence the concept of Mark-compact.

3.2.2 mark – compact

After mark-Sweep is completed, there will be a lot of memory fragmentation in the old generation region, which will cause problems when a large object needs to be allocated. Therefore, the concept of Mark-Compact is proposed. After the mark sweep is completed, the memory fragmentation will be cleaned, and all the active objects will be moved to one end. Clean up the memory outside the boundary.

4. stop-the-world

Avoid inconsistency caused by memory resource contention.

Since garbage collection takes place in the JS engine, and Mark-Compact moves objects during markup, this process can be time-consuming when there are many live objects. To avoid inconsistencies caused by competing JavaScript application logic and garbage collector memory resources, The garbage collector pauses the JavaScript application. If there are many live objects in the old generation, the garbage collector will pause the main thread for a long time, causing the page to become stagnant.

5. Optimize the Orinoco

Garbage collection is optimized to reduce the main thread hang time

5.1 Incremental Mark

Mark active/inactive objects through each phase of the main thread, marking only

5.2 Lazy cleaning

A lazy cleanup is triggered when the threshold is reached. Incremental markers and lazy cleanup significantly reduce the pause time of the host thread, making the user’s interaction with the browser much smoother.

From an implementation point of view, since JavaScript code is executed between each small increment price, the object pointer in the heap may change, and write barriers are required to record these changes in reference relationships, thus exposing the disadvantages of the increment tag:

  • Does not reduce the total pause time of the main thread
  • Due to the cost of a write barrier mechanism, it can be applied with increased overhead
5.3 concurrent

The parallel GC does not need to suspend the main thread while marking, and only occasionally needs to stop briefly for the garbage collector to do some special operations. A pointer synchronization problem exists. Procedure Write barriers are required.

5.4 the parallel

A single GC can be handed over to multiple threads at the same time, also introducing write barriers.

V8 current garbage collection mechanism

In 2011, Chrome introduced incremental markup. Chrome64 and Node V10 have enabled concurrency flags in 2018. It also introduces the synchronization problem caused by multi-threading.

6.1 Secondary garbage collector

V8 uses the parallel mechanism in the new generation garbage collection. In the sorting stage, multiple auxiliary threads are enabled to carry out sorting in parallel.

6.2 Main garbage collector

V8’s legacy garbage collection enables concurrent flags when memory in the heap exceeds a certain threshold, assisting threads to track Pointers and references to objects. If the object changes during the process, write barrier technology tracks the pointer. When the concurrent marker completes or memory reaches its limit, the main thread takes over: checks against the root set, and then GC.

Homework: List of nouns related to GC:

Cenozoic region; nursery; intermediate; Old age area; Object promotion; Mark-sweep; Mark-compact marking; Stop-the-world c. Optimize the Orinoco; Incremental mark; Inert cleaning; Concurrent concurrent; Parallel to the parallel; Subgarbage collector; Main garbage collector; Active/inactive objects; Garbage recycling process;

reference

In-depth understanding of Chrome V8 garbage collection

Orinoco: V8 garbage collector

Trash talk: the Orinoco garbage collector

Chrome garbage collection mechanism and memory leak analysis

Stack and garbage collection in JavaScript

Super detailed node/ V8 / JS garbage collection mechanism

Garbage collection technology

Class 4 JavaScript memory Leaks and how to avoid them

Memory management

Memory management and V8 garbage collection mechanisms in Nodejs

Memory management crash course