JavaScript garbage collection mechanism and memory leak detailed parsing _javascript tips

Source: Internet
Author: User
Tags closure garbage collection memory usage object model time interval

JavaScript has an automatic garbage collection mechanism, which means that the execution environment is responsible for managing the memory used during code execution. In languages such as C and C + +, a basic task for developers is to manually track memory usage, which is one of the root causes of many problems. When writing JavaScript programs, developers no longer have to worry about memory usage, the allocation of required memory, and the need for garbage collection to fully automate management. The principle of this garbage collection mechanism is simple: identify the variables that are no longer in use, and then release the memory occupied by them. To do this, the garbage collector periodically performs this operation at a fixed time interval (or a preset collection time in code execution).

Let's analyze the normal life cycle of local variables in the function. Local variables exist only during the execution of a function. In this process, the local variables are allocated space on the stack (or heap) memory to store their values. These variables are then used in the function until the function execution ends. At this point, local variables are not necessary to exist, so they can be freed for future use. In this case, it is easy to judge whether a variable is still necessary, but not in all cases it is so easy to draw a conclusion. The garbage collector must keep track of which variable is useful and which variable is useless, marking the variables that are no longer useful for future recall of the memory they occupy. The policies used to identify the useless variables may vary by reality, but the implementation in the browser typically has two policies.

Mark Clear

The most common method of garbage collection in JavaScript is tag Cleanup (mark-and-sweep). When a variable enters the environment (for example, declaring a variable in a function), it marks the variable as "entering the environment." Logically, you will never be able to release the memory of variables that enter the environment, because they may be used as long as the execution stream enters the appropriate environment. When a variable leaves the environment, it marks it as "away from the environment."

You can tag variables in any way. For example, you can track which variable has changed by flipping a particular bit to record when a variable enters the environment, or by using a "go to environment" variable list and a list of variables to leave the environment. In the final analysis, it doesn't matter how you label variables, but what strategies you take.

The garbage collector will mark all variables stored in memory at run time (and, of course, any markup method can be used). It then removes the variables in the environment and the variable tags that are referenced by the variables in the environment. Variables that are then tagged later are considered variables to be deleted because variables in the environment are already inaccessible to these variables. Finally, the garbage collector completes the memory cleanup work, destroys those tagged values, and reclaims the memory space they occupy.

By 2008, the JavaScript implementations of IE, Firefox, Opera, Chrome, and Safari used all the tagging-purge garbage collection policies (or similar policies), except that the time interval for garbage collection was different.

Reference count

Another less common garbage collection strategy is called a reference count (reference counting). Reference counting means tracking the number of times each value is referenced. When you declare a variable and assign the value of a reference type to the variable, the number of references to that value is 1. If the same value is assigned to another variable, the number of references to that value is 1. Conversely, if a variable that contains a reference to this value gets another value, the reference number of that value is reduced by 1. When the number of references to this value changes to 0 o'clock, there is no way to access the value, so you can reclaim the memory space it occupies. The next time the garbage collector is run, it releases the memory occupied by values that have a reference number of zero.

Netscape Navigator 3.0 was the first browser to use the reference counting policy, but soon it ran into a serious problem: circular references. A circular reference means that object A contains a reference to object B, and object B also contains a reference to object A.

Take a look at the following example:

Copy Code code as follows:

function () {
var objecta = new Object ();
var OBJECTB = new Object ();

Objecta.someotherobject = OBJECTB;
Objectb.anotherobject = Objecta;
}

In this example, Objecta and OBJECTB are referred to each other by their respective attributes, that is, the two objects are referenced 2 times. In an implementation that takes the lead-mark cleanup slightly, both objects leave the scope after the function is executed. So these two kinds of cross-references are not a problem. However, in the implementation of the reference counting policy, the objecta and OBJECTB will continue to exist after the function has been executed, so their reference times will never be 0. If this function is called repeatedly, it can cause a lot of memory to be recycled. as a result, Netscape abandoned the reference counter in Navigator 4.0, instead using tag cleanup to implement its garbage collection mechanism. However, the trouble with reference counting has not ended.

We know that some of the objects in IE are not native JavaScript objects. For example, objects in the BOM and Dom are implemented using C + + as a COM (Component object model, Component Object Modeling) object, and the garbage collection mechanism for COM objects is a reference-counting policy. Therefore, even though IE's JavaScript engine is implemented using a tag-purge policy, the COM objects that JavaScript accesses are still based on the reference-counting policy. In other words, as long as the COM object is designed in IE, there will be a circular reference problem.

The following simple example shows a circular reference problem caused by using a COM object:

Copy Code code as follows:

var element = document.getElementById ("some_element");
var myObject = new Object ();
Myobject.element = element;
Element.somobject = MyObject;

Here The example creates a circular reference between a DOM element (element) and a native JavaScript object (myObject). Where the variable MyObject has a property named element that points to the element object, and the variable element also has a property named Someobject Anaphora MyObject. Because of this circular reference, it will never be reclaimed, even if the DOM in the example is removed from the page.

To avoid such circular reference problems, it is best to manually disconnect the native JavaScript objects from the DOM elements when they are not used. For example, you can use the following code to eliminate the circular references created in the previous example:

Copy Code code as follows:

Myobject.element = null;
Element.somobject = null;

Setting a variable to null means severing the connection between the variable and the value it previously referenced. But the next time the garbage collector runs, it deletes the values and reclaims the memory they occupy.

Performance issues

The garbage collector is run periodically, and if the amount of memory allocated to a variable is objective, then the amount of work to be collected is quite substantial. In this case, determining the time interval for garbage collection is a very important issue. When it comes to how long the garbage collector runs, it makes people think of IE's notorious performance problems. The IE garbage collector runs according to memory allocations, specifically 256 variables, 4,096 objects (or array) literals and arrays of elements (slot) or 64KB strings. When any of these thresholds are reached, the garbage collector runs. The problem with this implementation is that if a script contains so many variables, the script is likely to hold as many variables in its life as possible. As a result, the garbage collector may have to run frequently. As a result, the severity of the problem caused by this initial IE7 overrides its garbage collection routines.

With the release of IE7, the garbage collection routines of its JavaScript engine change the way it works: the variable allocations that trigger the garbage collection, the literal and/or the critical values of the array elements are adjusted to dynamic corrections. The critical values in IE7 are equal to IE6 when initialized. If a routine reclaims less than 15% of the memory allocated, the threshold value of the variable, literal, and/or array element is doubled. If the routine reclaims 85% of the memory allocations, a variety of critical resets will be default values. This seemingly simple adjustment greatly increases the performance of IE when running pages that contain a lot of JavaScript.

In fact, the garbage collection process can be triggered in some browsers when we do not recommend the reader to do so. In IE, call window. The CollectGarbage () method immediately points to garbage collection, and in Opera7 and later versions, calling Widnow.opera.collect () also initiates the garbage collection routine.

Manage memory

Developers are generally not bothered with memory management issues by making programs that have a garbage collection mechanism written in a language. However, the problems that JavaScript faces in memory management and garbage collection are somewhat different. One of the most important problems is that the amount of available memory allocated to a Web browser is typically less than that allocated to a desktop application. This is done in the context of security considerations to prevent a Web page running JavaScript from draining all system memory and causing the system to crash. The memory limit problem not only affects allocating memory to variables, but also affects the call stack and the ability to execute the number of statements simultaneously in one thread.

Therefore, ensuring that the least amount of memory is used allows the page to get better performance, preferably by setting its value to null to release its reference-a practice called a dereference (dereferencing). This approach is used for the properties of most global variables and global objects. Local variables are automatically dereference when they execute the environment, as shown in the following example:

Copy Code code as follows:

function Createperson (name) {
var Localperson = new Object ();
Localperson.name = name;
return Localperson;
};
var Gllbalperson = Createperson ("Nicholas");

Manually dismiss a Globalperson reference
Globalperson = null;


In this example, the variable Globalperson gets the value returned by the Createperson () function. Inside the Createperson () function, we create an object and assign it to the local variable Localperson, and then add a property named Name to the object. Finally, when this function is called, Localperson is returned as a function and assigned to the global variable Globalperson. Since Localperson has left its execution environment after the Createperson () function has been executed, it does not need to be shown to dereference him. But for the global variable Globalperson, we need to manually dereference it when we don't use it, which is exactly the last line of code in the example above.

However, lifting a reference to a value does not automatically reclaim the memory occupied by the value. The real effect of the dereference is to leave the value out of the execution environment and recycle the garbage collector the next time it runs.

Memory leaks

Because IE uses different garbage collection routines for JScript objects and COM objects, closures can cause special problems in IE. Specifically, if an HTML element is stored in the scope chain of the closure, it means that the element cannot be destroyed. Look at the following example:

Copy Code code as follows:

function Assignhandler () {
var element = document.getElementById ("someelement");
Element.onclick = function () {
alert (element.id);
};
};

The above code creates a closure that acts as a time handler for element elements, and the closure creates a circular reference. Because the anonymous function holds a reference to the active object of Assignhandler (), it causes the reference number of the element to be reduced. As long as the anonymous function exists, the number of references to the element is at least 1, so the memory it occupies will never be reclaimed. However, this problem can be solved by slightly rewriting the code, as follows:
Copy Code code as follows:

function Assignhandler () {
var element = document.getElementById ("someelement");
var id = element.id;

Element.onclick = function () {
alert (ID);
};

element = null;
};

In the code above, the circular reference is eliminated by saving a copy of element.id in a variable and referencing the variable in the closure. But only in this way, still can not solve the memory leak problem. It must be remembered that the closure refers to the entire active object that contains the function activity, which contains the element. Even if the closure does not refer to the element directly, a reference is still saved in the active object that contains the function. Therefore, it is necessary to set the element variable to null. This allows a reference to the DOM object to be lifted, smoothly reducing its reference count, and ensuring that the memory it occupies is properly recycled.

Description

1. If you keep the object's reference in the window in another window, the memory is not released even if the window is closed;

2, worse, if you keep a DOM object reference, close the object Window,ie will crash, report the memory error (or request, reboot).

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.