1. Garbage recycling mechanism - GC
Javascript has an automatic garbage collection mechanism (GC:Garbage Collection), which means that the execution environment is responsible for managing the memory used during code execution.
Principle: The garbage collector periodically (periodic) finds variables that are not in use and then frees their memory.
The mechanism of JavaScript garbage collection is very simple: find out variables that are no longer used and then free up the memory it occupies. However, this process is not real-time because its overhead is relatively large, so the garbage collector will execute periodically at fixed time intervals .
Variables that are no longer used are variables that end the life cycle. Of course, they can only be local variables. The life cycle of the global variable will not end until the browser uninstalls the page. Local variables only exist during the execution of the function, and in this process, the corresponding space will be allocated for local variables on the stack or heap to store their values, and then these variables are used in the function until the end of the function. However, due to internal functions in the closure, external functions cannot be considered ending.
Let's just explain the code:
function fn1() { var obj = {name: 'hanzichi', age: 10};} function fn2() { var obj = {name:'hanzichi', age: 10}; return obj;} var a = fn1();var b = fn2();Let's see how the code is executed. First, two functions are defined, called fn1 and fn2. When fn1 is called, entering the fn1 environment will open a memory storage object {name: 'hanzichi', age: 10}. When the call is finished and the fn1 environment is out, the block of memory will be automatically released by the garbage collector in the js engine; during the process of fn2 being called, the returned object is pointed to by the global variable b, so the block of memory will not be released.
Here the question arises: Which variable is useless? Therefore, the garbage collector must track which variable is useless and mark variables that are no longer useful in order to reclaim its memory in the future. The strategies for useless variables used to tag may differ by implementation, and there are usually two ways to do this: mark clearance and reference counting. Quotation counting is not very common, mark clearing is more commonly used.
2. Clear mark
The most commonly used garbage collection method in js is mark removal. When a variable enters the environment, for example, declare a variable in a function, it marks the variable as "enter the environment". Logically speaking, the memory occupied by variables entering the environment cannot be released, because they may be used as long as the execution flow enters the corresponding environment. And when a variable leaves the environment, it is marked as "out of the environment".
function test(){ var a = 10; // is marked, enter the environment var b = 20; // is marked, enter the environment}test(); //After execution, a and b are marked, leave the environment and are recycled.When the garbage collector runs, it marks all variables stored in memory (of course, any marking method can be used). It then removes the tags (closures) of variables in the environment and variables referenced by variables in the environment. The variables marked after this will be considered as variables ready to be deleted because variables in the environment can no longer access these variables. Finally, the garbage collector completes the memory clearing work, destroying those marked values and reclaiming the memory space they occupy.
So far, the js implementations of IE, Firefox, Opera, Chrome, and Safari use mark-clearing garbage collection strategies or similar strategies, but the time intervals of garbage collection are different from each other.
3. Quotation count
The meaning of reference count is to keep track of the number of times each value is referenced. When a variable is declared and a reference type value is assigned to the variable, the number of references to this value is 1. If the same value is assigned to another variable, the number of references to the value is increased by 1. On the contrary, if the variable containing the reference to this value takes another value, the number of references to this value is reduced by 1. When the number of references to this value becomes 0, it means that there is no way to access the value again, so the memory space it occupies can be reclaimed. This way, when the garbage collector runs again next time, it frees up memory that values with 0 references.
function test(){ var a = {} ; //The number of references of a is 0 var b = a ; //The number of references of a is 1 var c =a; //The number of references of a is 1, and the number of references of a is 1, and the number of references of a is 1, and the number of references of a is 2 var b ={}; //The number of references of a is 1, and the number of references of a is 1}Netscape Navigator3 was the first browser to use the reference counting strategy, but soon it encountered a serious problem: circular references. A circular reference refers to an object A containing a pointer to object B, and object B also contains a reference to object A.
function fn() { var a = {}; var b = {}; a.pro = b; b.pro = a;} fn();The reference times of a and b above are 2. After fn() is executed, both objects have left the environment. There is no problem in the mark clearing mode. However, under the reference counting strategy, because the reference times of a and b are not 0, memory will not be collected by the garbage collector. If the fn function is called in large quantities, memory leakage will occur. On IE7 and IE8, the memory rises sharply.
We know that some objects in IE are not native js objects. For example, the objects in the DOM and BOM are implemented in the form of COM objects using C++, and the garbage collection mechanism of COM objects adopts a reference counting strategy. Therefore, even if the IE js engine adopts a tag clearing strategy, the COM objects accessed by js are still based on the reference counting strategy. In other words, as long as COM objects are involved in IE, there will be a problem of circular references.
var element = document.getElementById("some_element");var myObject = new Object();myObject.e = element;element.o = myObject;This example creates a circular reference between a DOM element and a native js object. Among them, the variable myObject has an attribute named element pointing to the element object; and the variable element also has an attribute named o back to refer to myObject. Due to this circular reference, even if the DOM in the example is removed from the page, it will never be recycled.
Looking at the example above, some students thought it was too weak. Who would do such a boring thing? In fact, are we doing it?
window.onload=function outerFunction(){ var obj = document.getElementById("element"); obj.onclick=function innerFunction(){};};This code seems to be fine, but obj refers to document.getElementById("element"), and the onclick method of document.getElementById("element") will refer to the German variable in the external environment, which naturally also includes obj. Isn't it very hidden?
Solution
The easiest way is to manually unreference the loop, for example, the function just now can do this.
myObject.element = null;element.o = null;
window.onload=function outerFunction(){ var obj = document.getElementById("element"); obj.onclick=function innerFunction(){}; obj=null;};Setting a variable to null means cutting off the connection between the variable and the value it previously referenced. When the garbage collector runs next time, these values are deleted and the memory they occupy is recycled.
It should be noted that IE9+ does not have a circular reference to cause Dom memory leaks. It may be that Microsoft has optimized it, or Dom's recycling method has changed.
4. Memory management
1. When will garbage collection be triggered?
The garbage collector runs periodically. If the allocated memory is very large, the recycling work will be very difficult. Determining the garbage collection time interval becomes a question worth thinking about. IE6's garbage collection runs according to the memory allocation. When there are any 256 variables, 4096 objects, and 64k strings in the environment, the garbage collector will be triggered. It looks very scientific and it doesn't need to be called once for a while. Sometimes it is unnecessary. Isn't it good to call on demand like this? But if there are so many variables in the environment, and the scripts are so complex and normal now, then the result is that the garbage collector is always working, so the browser cannot play.
Microsoft has made adjustments in IE7. The trigger conditions are no longer fixed, but dynamically modified. The initial value is the same as IE6. If the memory allocation collected by the garbage collector is less than 15% of the memory occupied by the program, it means that most of the memory cannot be recycled. The set garbage collection trigger conditions are too sensitive. At this time, double the street conditions. If the collected memory is higher than 85%, it means that most of the memory should be cleaned long ago. At this time, the trigger conditions are set back. This makes the garbage recycling work more functions
2. Reasonable GC solution
1) The basic GC solution of Javascript engine is (simple GC): mark and sweep, i.e.:
2) GC defects
Like other languages, JavaScript's GC policy cannot avoid one problem: when GC, stop responding to other operations, which is for security reasons. Javascript's GC is 100ms or even above, which is good for general applications, but for JS games, applications that require high coherence are troublesome. This is what the new engine needs to optimize: avoid long-term stopping response caused by GC.
3) GC optimization strategy
Uncle David mainly introduced two optimization solutions, and these are also the most important two optimization solutions:
(1) Generation GC)
This is consistent with the Java recycling strategy idea. The purpose is to distinguish between "temporary" and "persistent" objects; recycle more "temporary object" areas and less "tenured object" areas, reduce the objects that need to be traversed each time, thereby reducing the time spent on GCs each time. As shown in the picture:
What needs to be added here is that for the tenured generation object, there is an additional overhead: migrate it from young generation to tenured generation, and if it is referenced, the reference pointing also needs to be modified.
(2) Incremental GC
The idea of this plan is very simple, which is to "treat a little bit each time, deal with a little bit next time, and so on." As shown in the picture:
Although this solution takes a short time, it has many interruptions, which brings the problem of frequent context switching.
Because each solution has its applicable scenarios and disadvantages, in actual applications, the solution will be selected according to the actual situation.
For example: when the (object/s) ratio is low, the frequency of the execution of GC is interrupted, and the simple GC is lower; if a large number of objects are "survived" for a long time, the advantage of generational processing is not great.
The above article comprehensively understands JavaSCIRP's garbage collection recycling mechanism is all the content I share with you. I hope it can give you a reference and I hope you can support Wulin.com more.