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