preface

What is garbage collection? Did you want to pick up your garbage in a garbage truck? Red in the East?

Is there anyone who thinks of recycling: rice cookers, high pressure sockets, gas ranges ~~~

In fact, today we are going to talk about memory garbage collection ~

The first time I learned about garbage collection was when I saw it on a public account. At that time, I talked about mark removal method and reference counting method, but there were many doubts at that time, such as what is reachable and unreachable bottom? I didn’t think much of it. Today to understand again, with their own words to share the summary. Hope to give you some inspiration and thinking.

This article contains the following information:

  • What is garbage collection
  • How to determine whether it is garbage
    • accessibility
  • What are the garbage collection algorithms? Their characteristics
  • A memory leak

One important thing to know before this article begins is the memory life cycle of JS. Today’s story is about memory release.

  • 1. Allocate memory for variables
  • 2. Use the allocated memory
  • 3. Release the memory when it is not needed

First, what is garbage recycling

First of all, I think garbage collection is hard to understand because it’s abstract. After all, it’s an operation inside the browser that we can’t see.

We can imagine that the discarded and useless things in our daily life are “garbage”. In order to occupy the space, we have to clean up the garbage. The same is true for JS memory management, except that it is automatic and invisible (but in languages without garbage collection, such as C).

Knowledge point 1

The JavaScript engine has a background process called the garbage collector that monitors all objects and removes those that are not accessible (garbage).

Knowledge point 2

When we create a string, array, etc., we treat it as an object (whether it’s a primitive type or a reference type) and create a memory space for the object to hold the variable. If the object is not accessible, it is garbage

So what, you might ask, are unreachable objects? How do you know if an object is reachable? Let me tell you one by one

How to judge garbage

How do you know if an object can be accessed? There’s a technical term for accessibility. Judge by whether the object is reachable.

accessibility

The main concept of memory management in JavaScript is reachability.

Simply put, “reachable” values are those that are accessible or available in some way that is guaranteed to be stored in memory. Let’s start with an example

// define a user object that references the name attribute const user={name:"john"
}
Copy the code

Here the arrow represents an object reference. The global variable user refers to the object {name: “John”}, and the “name” attribute of user stores a primitive type, so it is drawn in the object.

If the value of user is overwritten, the reference is lost:

Case 1

// make the reference to user null user=nullCopy the code

The arrows in the figure represent references. In the first figure, user refers to the name attribute. In the second figure, the user pointer is empty, the arrow disappears, and the user cannot refer to the name attribute.

Circle a key 👇

When the user has access to the name attribute, the name is reachable; If it is not accessible then name is unreachable.

Do you have a basic understanding of reachability from the example above? And then we go into accessibility.

  • There is a basic set of inherently reachable values that cannot be removed for obvious reasons, such as:

    • Local variables and arguments of a local function

    • Currently nested variables and arguments of other functions on the call chain

    • The global variable

    • There are some other ones, internal ones

These values are called roots.

  • A reference or chain of references is considered accessible if any other value can be accessed from the root.

Now we have one more concept which is roots. Let’s look at an example.

Case 2

// User has a reference to an objectlet user = {
  name: "John"
};

let admin = user;
Copy the code

admin=null;
Copy the code

The result is the name property is still reachable. Why? Admin’s reference to name has already been removed.

The reason: although Admin has no way of referring to name, user can still refer to the name attribute, so it can be accessed from the root and therefore reachable.

If user=null; Then name will become unreachable. The name attribute cannot be referenced from the root at this point.

The pictures above are all from here. Let’s move on to see what the garbage collection algorithms are.

Third, garbage collection algorithm

Here are the two main collection algorithms. If you want to know more about tag compression, GC replication, etc. Click here

Reference counting method

Reference counting is also easy to understand, where a reference counts the number of references. Add 1 if the reference increases, subtract 1 if the reference decreases. Clear the reference when it equals 0. Let’s look at an example

  • Example 3
// if there is a counter count=0let a ={
    name:'linglong',//count==1
}
letb=a; //count==2 b=null; //count==1 a=null; / / count = = 0, be clearedCopy the code

If there is a reference counter count, proceed with the above four steps, and reference name from 0->1->2->1->0. It’s recycled.

Reference counting problems

One fatal problem with reference counting is circular references. If two objects refer to each other and are no longer used, they go through an infinite loop and the garbage collector does not collect them. Look at the following code

  • Example 4
function cycle(){
    var o1={};
    var o2={};
    o1.a=o2;
    o2.a=o1;
}
cycle();
Copy the code

The cycle function in this code is no longer needed, so the memory of O1 and O2 should be freed, but they reference each other so that memory can’t be reclaimed. This method is not used nowadays, but it was still used before IE9. The most commonly used method is the tag elimination method introduced later.

Mark clearing algorithm

Mark removal is a two-step process, marking and then removing the unmarked.

  • The garbage collector gets the root andtag(Remember) them.
    • It then accesses and “flags” all references from them.
    • It then accesses the tagged objects and marks their references. All objects accessed are remembered so that the same object is never accessed twice in the future.
    • And so on, until there are unaccessed references that can be accessed from the root.
  • All objects except those marked are marked byremove.

For example, the object structure is as follows:

  • The first step is to mark the root

  • Now unreachable objects in the process are considered unreachable and will be removed:

Tag clearing algorithm data structure

Mark removal takes advantage of the heap and linked list structure marking stage: starting from the root set, all active objects and their children are marked. Mark removal stage: traversing the heap, connecting inactive (unmarked) objects to the free list

This is how garbage collection works. The JavaScript engine applies a number of optimizations to make it run faster without affecting execution.

V8 engine some optimizations:

Generational recycling

Objects in the V8 heap objects are divided into two groups: new generation and old generation

  • New generation: Most object creation is allocated here. This area is small, but garbage collection is frequent and has short lifetime independent of other areas such as temporary variable strings
  • The old generation
    • Old-generation pointer area: contains most objects that may contain Pointers to other objects. Most objects promoted from the new generation (surviving for a period of time) are moved here.
    • Old generation data: extents contain raw data objects (no Pointers to other objects). Strings, Boxed Numbers, and the double-precision Unboxed array were moved here after being promoted from the new generation.
The incremental recovery

If there are many objects and we try to traverse and mark the entire set of objects at once, it may take some time and there will be some delay in execution. Therefore, the engine attempts to decompose garbage collection into multiple parts (proposed in 18). Then, each part is executed separately. This requires extra markers to keep track of changes, so there are lots of tiny delays, not big ones.

Idle time collection

The garbage collector runs only when the CPU is idle to reduce possible impact on execution.

Memory leaks

Since memory leaks are related to memory not being released, here is a brief introduction to when memory leaks occur.

1.

What is a memory leak? The memory that is no longer used is called a memory leak if it is not released in time.

This has nothing to do with leaks??

The way I understand it is that memory is like sand in the palm of your hand. When the sand leaks out of your hand, there is less and less memory available. This process is a memory leak.

The hand can not hold the sand, it is better to raise it

But the memory leak is still to be taken care of, how to be responsible for it, please continue to see

Four types of memory leaks

Now that we understand the concept of memory leaks, we need to know that there are several ways memory leaks can occur

  • Unexpected global variables (strict mode resolution)
  • Forgotten timers and callback functions
  • Out-of-dom references
  • Closure (variable reference to null resolve)

The first and fourth ones are easy to understand. If you have any questions, linglong is welcome in the comments section. I’m going to focus on 2 and 3.

  • Forgotten timers and callbacks

When setInterval or setTimeout is not required, the timer is not cleared, and the callback function and internal dependent variables of the timer cannot be reclaimed, causing memory leakage.

 timeout = setTimeout(() => {
 var node = document.getElementById('node');
    if(node){ fn(); }}, 1000);Copy the code

Solution: Manually clear the timer when the timer is finished. timeout=null

  • 3. Out-of-dom references
<body>
    <div id="fa">
        <button id="button"></button>
    </div>
    <script>
        let div=document.getElementById('fa'); document.body.removeChild(div); // dom removed //div=null // cut off div references to div console.log(div); </script> </body>Copy the code

Results:

<div id="fa">
        <button id="button"></button>
 </div>
Copy the code

Let div= document.getelementById (‘fa’); let div= document.getelementById (‘fa’); There is a div to div reference in this line of code.

Solution: We cut out both references with div=null.

Other memory leaks

In addition to the above four, if there are other memory leaks welcome to point out, learn together, hee hee hee

Identification of memory leaks

The content of the memory leak identification method comes from the suggestion of LinDaiDai_ Lin Nerdy little brother, the author of Super Nice 😃😉

1. Recognition in browser (Chrome console Performance or Memory)

Here’s how to view it in Performance. The main steps are as follows:

  1. Right-click on a web page and click “Check” to open the console (Mac shortcut Option + Command + I).
  2. Select the Performance panel (Step 1 below)
  3. Select Memory and then click the small black dot Record in the upper left corner to start recording (steps 2 and 3 in the image below)
  4. Click Stop in the popup window to end recording, and the memory usage during this period will be displayed on the panel.

    Finish the first three steps and start recording like this.

    After the recording of episode 4, the picture is as follows. If memory usage keeps incrementing, it’s a memory leak.

    Ps: You can also check the Memory panel in the consoleThe early LinDaiDai_ gawktheLog memory leaks caused by timer and closure problemsThis is explained in detail in the article

2. Command line methods

The command line can use the Process. memoryUsage method provided by Node. Linglong is not familiar with Node.js and did not know this method before this. A review of official documents reveals that:

Process is a global variable, a property of the Global object that describes the current state of the Node.js process.

MemoryUsage is a method under Process that returns an object describing the memory used by the Node process, in bytes.

Let’s try it out

  1. Create a new main.js file and type the following code
const fun = () => { console.log(__filename); // The absolute path to the file location console.log(Here is the memory usage information:);
    console.log(process.memoryUsage());
}
fun();
Copy the code
  1. Enter node main.js in the terminal and press Enter to see the result, as shown below:

We see that process.memoryUsage returns an object containing memoryUsage information for Node processes. This object contains four fields, in bytes, with the following meanings.

RSS (residentsetSize) : All memory footprint, including instruction area and stack. HeapTotal:"Pile"Occupied memory, both used and unused. HeapUsed: part of the heapUsed. External: memory occupied by C++ objects inside the V8 engine.Copy the code

Note: Use the heapUsed field to determine memory leaks.

Finally, a question to consider: How to reduce memory leaks? Leave a comment in the comments section

conclusion

Give yourself a big thumbs up and ask yourself:

  • What is garbage collection and what is accessibility
  • Garbage collection algorithms, which two
  • What are the common memory leaks and how can they be solved

Read carefully there will be harvest drops, than the heart ~

Linglong thought she could talk a lot about garbage collection algorithms. Starting from the memory mechanism, what is garbage collection, garbage collection algorithm, v8 engine how to recycle, etc., memory leakage, and ES6 Chinese Weakset and WeakMap which are not included in the garbage collection mechanism of weak reference….

If I have what understanding wrong place also ask digg friends to point out, if mislead everybody embarrassing

In addition, the article cover “except money is garbage” is a joke, after all, there are a lot of things higher than MAO Grandpa, such as your star~ and messages!

Thanks again LinDaiDai_ Lin stupid little brother’s encouragement and help!

Refer to the article

Talk about JS garbage collection

Recommended reading

  • Garbage collection mechanism in JS elevation and common solutions to memory leaks
  • Several garbage collection algorithms

See you in the next article…