js garbage collection and memory leaks

js garbage collection

concept:

javascript automatic garbage collection mechanism, that is, memory usage procedure code execution will be responsible for environmental management. In languages ​​like C and C ++ class, a fundamental task of the developer is to manually track memory usage, which is a root cause of many problems. When writing javascript program, developers no longer need to be concerned about memory usage problems, the required memory allocation and garbage recycling full realization of automatic management.

The most commonly used JavaScript garbage collection is labeled Clear (mark-and-sweep). When the variable into the environment (e.g., a variable declared in a function), this variable will be marked as "into the environment." Logically, never release the memory occupied by variables into the environment, as long as the corresponding execution flow into the environment, it is possible to use them. When leaving the environment variable, which will mark it as "leaving the environment."

Collection algorithm: Mark-and-sweep

Most of the language with garbage collection algorithm called Mark-and-sweep. Algorithm consists of the following steps:

  1. Garbage collector creates a "roots" list. Roots are usually referenced in the code of global variables. In JavaScript, "window" object is a global variable is treated as root. window object always exists, so the garbage collector can check it and all its child objects exist (i.e., not spam);
  2. All the roots are checked and marked as active (ie not spam). All child objects are also recursively check. All objects starting from the root if it is reachable, it will not be garbage.
  3. All memory is not marked as garbage collector can now release the memory, returned to the operating system.

It does not require reference is to the developer knowingly memory reference is no longer needed, but for some reason, it still remain in the active root tree. In JavaScript, no reference is retained in the variable code, it is no longer necessary, but the present point to a memory is released.

What rubbish means:

After the end of the life cycle of a variable it points to memory should be released. JS two variables, global and local variables in the function generated. The life cycle of a local variable after function execution is over, then it can be referenced memory release (ie garbage), but the global variable life cycle will continue until the browser is closed page.

Memory Leak

concept:

Means the program has been dynamically allocated heap memory for some reason the program does not release or not release, resulting in a waste of system memory, causing the program to run slower and even system crashes and other serious consequences.

Common causes:

  1. Global variables caused by a memory leak

  2. Packet memory leak caused by closure

  3. When dom empty or deleted, the event did not clear the memory leak caused

  4. Forgotten timer or callback

  5. Closure

Factor explains:

1: Unexpected global variables

JavaScript is way more relaxed handling undefined variables: Undefined variable creates a new variable in the global object. In the browser, the global object is window.

function foo(arg) {
bar = "this is a hidden global variable";
}
真相是:

foo function (Arg) {
window.bar = "Explicit Global the this variable IS AN";
}
internal function foo forgets var, accidentally create a global variable. In this case it leaked a simple string, harmless, but there are worse situations.

Another unexpected global variables may be created by this:

foo function () {
this.variable = "Global potential Accidental";
}

// Foo call itself, this points to the global object (window)
// instead undefined
foo ();
in a JavaScript file header plus 'use strict' to avoid such errors. Enable strict mode parsing JavaScript, avoid unexpected global variables.

Global variables Note

Although we discussed some unexpected global variables, but there are still some clear global variables generated garbage. They are defined as non-recoverable (unless defined as empty or reallocation). Especially when global variables used for temporary storage and processing large amounts of information need to be careful. If you must use a global variable to store large amounts of data to ensure that it is set to run out after null or redefined. A main cause of global variables associated with increased memory consumption is cached. Cached data is to be reused, the cache must have a size limit to be useful. High memory consumption causes the cache to break the upper limit, because the cache contents can not be recovered.

2: The Forgotten or timer callback function

In JavaScript using setInterval very common. Common section of code:

someResource the getData = var ();
the setInterval (function () {
var node = document.getElementById ( 'the Node');
IF (node) {
// node processing and someResource
node.innerHTML the JSON.stringify = (someResource));
}
} , 1000);
this example illustrates what: the data associated with the node or the timer is no longer needed, node objects can delete the entire callback function is not needed. However, the timer callback function is still not been recovered (the timer is stopped will be recycled). Meanwhile, someResource If you store a lot of data, but also can not be recycled.

For example, the observer, once they are no longer needed (or the associated object becomes unreachable), remove them clearly very important. Old IE 6 can not handle circular references. Today, even if not explicitly remove them once the observer object becomes unreachable, most browsers can be recycled observer handler.

Observer Code Example:

Element document.getElementById = var ( 'Button');
function the onClick (Event) {
element.innerHTML = 'text';
}

element.addEventListener ( 'the Click', the onClick);
the object and the observer circular reference Considerations

Older versions of IE is unable to detect circulating between the DOM node with JavaScript code references, can lead to memory leaks. Today, modern browsers (including IE and Microsoft Edge) use the more advanced garbage collection algorithms have been correctly detect and handle the circular references. In other words, the recovery node memory, do not have to call the removeEventListener.

3: references from the DOM

Sometimes, save DOM node internal data structures useful. If you want to quickly update a few lines of the table, each row DOM deposit into a dictionary (JSON key-value pairs) or an array of great significance. In this case, the presence of the same two reference DOM element: a DOM tree, and the other in the dictionary. You decide to remove the rows, it requires two references to the future are clear.

Elements = {var
Button: document.getElementById ( 'Button'),
Image: document.getElementById ( 'Image'),
text: document.getElementById ( 'text')
};

function doStuff () {
's image.src = 'HTTP: //some.url/image ';
Button.Click ();
the console.log (text.innerHTML);
// more logic
}

function removeButton, for the () {
// the button body is descendant elements
document.body.removeChild (document .getElementById ( 'Button'));

// At this time, still present a global reference #button
// elements dictionary. button element remains in memory, it can not be recovered GC.
}
Moreover, it should consider the internal DOM tree node or sub-reference issues. If your JavaScript code saved one table <td> references. Future decided to delete the entire table when the GC will intuitively think in addition to the recovery of other nodes saved <td> outside. Is not the case: this <td> is a child node of the table, with the sub-elements parent element is a reference to the relationship. Since the code reserved <td> references, yet cause the entire table in memory. Save DOM element reference time, be careful.

4: Closures

Closure is an important concept of the JavaScript language:

Closure to read other functions is a function of internal variables. For example in javascript, only the internal function subroutine to read the local variables, so that the closure can be understood as "in the definition of a function within the function." In essence, the closure internal bridge function and the function of connecting external.

Code Example:

var theThing = null;
var replaceThing = function () {
var originalThing = theThing;
var unused = function () {
if (originalThing)
console.log("hi");
};

theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log(someMessage);
}
};
};

setInterval(replaceThing, 1000);
Code snippets to do one thing: Each replaceThing call, theThing get a big array and a new closure (someMethod) of the new object contains. At the same time, unused variable is a reference originalThing closure (previous replaceThing in turn calls the theThing). Confused thoughts yet? The most important thing is that the scope of the closure once created, they have the same parent scope, the scope is shared. someMethod theThing by using someMethod scope and closure sharing unused, unused although never used, it refers to originalThing forcing it remains in memory (to prevent recovery). When this code is run repeatedly, you will see the memory usage rise, the garbage collector (GC) and was unable to reduce the memory footprint. In essence, the list of closures has been created, each carrying a closure scope of indirect references a pointer to an array of large, serious memory leak.

 

Memory leak detection

Chrome offers a great tool to detect JavaScript memory footprint. Two important tool for memory-related: timeline and profiles.

Timeline

 

timeline may not need to detect the code memory. In this screenshot, we can see stable growth potential leak objects, when the end of data collection, memory usage significantly higher than the initial acquisition, the total amount (node) of the Node is also high. There are indications that the situation DOM node disclose the existence of the code.

Profiles

 

Profiles are tools you can spend a lot of time concerned, it can save snapshots, compare different snapshots of memory usage of JavaScript code, you can also record the time allocated. The result of each contain different types of lists, associated with memory leaks are summary (summary) and Comparison list (control) list.

summary (summary) shows the distribution list and the total size of the different types of objects: shallow size (total size of all objects of a particular type), retained size (shallow size plus other objects associated with this size). It also provides a concept from GC root of an object associated with.

Compare different comparison list snapshots can find memory leaks.

Example: Using Chrome find memory leaks

There are essentially two types of leaks: leaks caused by periodic memory growth, and even now the memory leak. Clearly, cyclical memory leaks is easy to find; sporadic leaks more difficult, generally easily overlooked, occasionally occurs once may be considered optimization problems, is considered a periodic occurrence must be solved bug.

Chrome to document the code as an example:

X = var [];

function createSomeNodes () {
var div,
I = 100,
the frag = document.createDocumentFragment ();

for (; I> 0; i--) {
div = document.createElement ( "div");
div .appendChild (document.createTextNode (I + "-" + new new a Date () toTimeString ()).);
frag.appendChild (div);
}

. document.getElementById ( "Nodes") the appendChild (the frag);
}

function Grow ( ) {
x.push (new new the Array (1000000) .join ( 'X'));
createSomeNodes ();
the setTimeout (grow, 1000);
}
when executed grow, and begin to create div node is inserted into the DOM, and to global variables allocated a huge array. It can be detected by a steady increase in the memory means mentioned above.

Find out the memory of cyclical growth

timeline label good at these. Open in Chrome example, open Dev Tools, switch to the timeline, check memory and click the Record button, and then click on The Button button on the page. Stop recording after a while to see the results:

 

Two kinds of indications that there was a memory leak, the figure Nodes (green line) and JS heap (blue line). Nodes steady growth, not decline, this is a significant signal.

JS heap memory usage is steady growth. Due to the garbage collector, not so easy to find. Display memory usage rose suddenly fell suddenly, in fact, after every fall, JS heap size than the original big figure. In other words, although the garbage collector continues to collect memory, the memory is still periodically leaked.

After determining the presence of a memory leak, we look for the root cause.

Save two snapshots

Switch to the profiles Label Chrome Dev Tools, and refresh the page, and so after page refresh is complete, click Take Heap Snapshot Save Snapshot as a benchmark. The Button then click on the button again, so after a few seconds, to save the second snapshot.

 

Filter menu select Summary, the right selection Objects allocated between Snapshot 1 and Snapshot 2, menu selection or screening Comparison, then you can see a list of comparison.

In this case it is easy to find memory leaks, look (string) of Size Delta Constructor, 8MB, 58 new objects. The new object is allocated, but did not release, it takes up 8MB.

If you expand the (string) Constructor, you will see a number of separate memory allocation. Select one single distribution, following retainers will attract our attention.

 

We have selected the assignment is part of an array of arrays associated to the window object variable x. Here we show the complete path to the object can not be recovered from the huge root (window) of. We have found a potential leak and its source.

Our example is fairly simple, just leaked a small amount of DOM node, using the above-mentioned snapshot is easy to find. For larger sites, Chrome also offers Record Heap Allocations function.

Record heap allocations find memory leaks

Back to the Chrome Dev Tools of profiles tab, click Record Heap Allocations. When the tool is running, note the blue bar at the top, represents the memory allocation, every second there are a lot of memory allocation. Stop running after a few seconds.

 

Killer tool can see the figure above mace: selecting one of the time line, the memory allocation can be seen in this time period. Selected close to the peak of the timeline as possible, the following list only shows the three constructor: One is the disclosure of the most serious (string), DOM next assignment is associated with the last one is Text constructor (DOM leaf nodes contain text ).

Select a HTMLDivElement constructor from the list, then select Allocation stack.

 

Now know where the elements are assigned to it (grow -> createSomeNodes), a closer look at the time line in the figure, found HTMLDivElement constructor call many times, means that the memory has been occupied, can not be recovered GC, we know these objects the exact location (createSomeNodes) assigned. Back to the code itself, to explore how to fix memory leak under it.

Another useful feature

In the Results section heap allocations choose Allocation.

 

This view presents a list of functions related to memory allocation, we immediately saw grow and createSomeNodes. When choosing grow, look at the relevant object constructor, clearly seen (string), HTMLDivElement and Text leaked.

 

Guess you like

Origin www.cnblogs.com/mingweiyard/p/11412541.html