Four types of JavaScript Memory leakage and how to avoid it

Source: Internet
Author: User
Tags chrome developer mozilla developer network microsoft edge
Original article: 4TypesofMemoryLeaksinJavaScriptandHowtoGetRidOfThem from: AlonsBlog this article will explore common client JavaScript memory leaks, and how to use Chrome to open...

Original article: 4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them

From: halon's Blog

This article will explore common client JavaScript memory leaks and How to Use Chrome development tools to discover problems.

Introduction
Memory leakage is the final problem that every developer will face. It is the root cause of many problems: slow response, crash, high latency, and other application problems.

What is memory leakage?
In essence, memory leakage can be defined as: when an application no longer needs to occupy memory, the memory is not recycled by the operating system or available memory pool for some reason. The memory management methods vary with programming languages. Only the developer knows which memory is not needed, and the operating system can recycle it. Some Programming Languages provide language features to help developers do such things. In addition, developers hope to be clear about the memory.

JavaScript Memory Management
JavaScript is a garbage collection language. The garbage collection language periodically checks whether the previously allocated memory is reachable to help developers manage the memory. In other words, the garbage collection language relieves the problem of "memory is still available" and "memory is still reachable. The difference between the two is subtle and important: Only developers know which inner will be used in the future, but the memory is not reachable through algorithm determination and marking, which will be recycled by the operating system in a timely manner.

JavaScript Memory leakage
The main cause of Memory leakage in the garbage collection language is unnecessary reference. Before learning about it, you also need to know how the garbage collection language identifies memory accessibility and accessibility.

Mark-and-sweep
The algorithms used in most garbage collection languages are called Mark-and-sweep. An algorithm consists of the following steps:

1. The Garbage Collector creates a "roots" list. Generally, the Roots is a reference to global variables in the code. In JavaScript, the "window" object is a global variable and is treated as root. The window object always exists, so the garbage collector can check whether it and all its sub-objects exist (that is, it is not garbage );
2. All the roots are checked and marked as activated (that is, not spam ). All sub-objects are also checked recursively. If all objects starting with root are reachable, they are not treated as garbage.
3. All unlabeled memory will be treated as garbage. The collector can now release the memory and return it to the operating system.
The modern Garbage Collector has improved the algorithm, but in essence it is the same: reachable memory is marked, and the rest are treated as garbage collection.

Unnecessary reference means that the developer knows that the memory reference is no longer needed, but for some reason, it is still in the active root tree. In JavaScript, a reference is a variable that is retained in the Code. It is no longer needed, but points to a piece of memory that should be released. Some people think this is a developer error.

To understand the most common memory leakage in JavaScript, we need to know which method of reference is easy to forget.

Three types of common JavaScript Memory leakage
1: unexpected global variables
JavaScript is loose in processing undefined variables: Undefined variables will create 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";}


The truth is:

function foo(arg) {    window.bar = "this is an explicit global variable";}


The function foo forgets to use var internally and creates a global variable unexpectedly. This example exposes a simple string, which is harmless but worse.

Another unexpected global variable may be created by this:

Function foo () {this. variable = "potential accidental global";} // Foo calls itself. this points to the global Object (window) // instead of undefinedfoo ();


Reference


Adding 'use strict 'to the header of a JavaScript file can avoid such errors. Enable strict mode parsing JavaScript to avoid unexpected global variables.


Global Variables

Although we have discussed some unexpected global variables, there are still some garbage generated by clear global variables. They are defined as unrecoverable (unless defined as null or reassigned ). Especially when global variables are used to temporarily store and process a large amount of information, you need to be careful. If you must use a global variable to store a large amount of data, make sure to set it to null or redefine it after use. One of the main reasons for increasing memory consumption related to global variables is cache. Cache data is used for reuse. The cache must have a maximum size. High memory consumption causes the cache to exceed the upper limit because the cached content cannot be recycled.

2: forgotten timer or callback function
It is very common to use setInterval in JavaScript. A common piece of code:

Var someResource = getData (); setInterval (function () {var node = document. getElementById ('node'); if (Node) {// process node and someResource node. innerHTML = JSON. stringify (someResource) ;}, 1000 );


In this example, the timer associated with the node or data is no longer needed, the node object can be deleted, and the entire callback function is no longer needed. However, the timer callback function is still not recycled (only when the timer is stopped will it be recycled ). At the same time, someResource cannot be recycled if it stores a large amount of data.

For Observer examples, it is important to remove them explicitly once they are no longer needed (or their associated objects become inaccessible. The old IE 6 cannot process circular references. Today, even if they are not explicitly removed, most browsers can recycle observer processing functions once the observer objects become inaccessible.

Sample observer code:

var element = document.getElementById('button');function onClick(event) {    element.innerHTML = 'text';}element.addEventListener('click', onClick);


Object observer and circular reference considerations

Earlier versions of IE cannot detect circular references between DOM nodes and JavaScript code, leading to memory leakage. Today, modern browsers (including IE and Microsoft Edge) use more advanced garbage collection algorithms to correctly detect and process circular references. In other words, you do not have to call removeEventListener to reclaim node memory.

3: Remove DOM references
Sometimes, it is useful to save the internal data structure of the DOM node. If you want to quickly update several rows of table content, it makes sense to save each row of DOM into a dictionary (JSON key-Value Pair) or array. At this time, the same DOM element has two references: one in the DOM tree and the other in the dictionary. In the future, when you decide to delete these rows, you need to clear both references.

Var elements = {button: document. getElementById ('button '), image: document. getElementById ('image'), text: document. getElementById ('text')}; function doStuff () {image. src = 'HTTP: // some. url/image'; button. click (); console. log (text. innerHTML); // more logic} function removeButton () {// The button is the descendant element of the body document. body. removeChild (document. getElementById ('button '); // At this time, a global # button reference // elements dictionary still exists. The button element is still in memory and cannot be recycled by GC .}


In addition, we also need to consider the reference problem of the DOM tree or sub-nodes. Assume that your JavaScript code saves a table. When we decide to delete the entire table in the future, we intuitively think that GC will recycleOther. This is not the case:Is the child node of the table, and the child element and the parent element are references. Because the code is retainedAs a result, the entire table remains in the memory. Exercise caution when saving DOM element references.

4: Closure
Closure is a key aspect of JavaScript development: anonymous functions can access variables in the parent scope.

Sample Code:

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 do one thing: every time you call replaceThing, theThing gets a new object that contains a large array and a new closure (someMethod. At the same time, the variable unused is a closure that references originalThing (the previous replaceThing calls theThing again ). Are you confused? The most important thing is that once a closure scope is created, it has the same parent scope and the scope is shared. SomeMethod can be used through theThing. someMethod shares the closure scope with unused. Although unused is never used, the originalThing referenced by it forces it to be kept in memory (to prevent being recycled ). When this code is run repeatedly, we can see that memory usage continues to rise, and the garbage collector (GC) cannot reduce memory usage. Essentially, the closure linked list has been created. Each closure scope carries an indirect reference pointing to a large array, causing serious memory leakage.

Reference

Meteor's blog post explains how to fix this problem. Add originalThing = null at the end of replaceThing.



Chrome memory profiling tool Overview
Chrome provides a great set of tools to detect JavaScript Memory usage. Two important memory-related tools: timeline and profiles.


var x = [];function createSomeNodes() {    var p,        i = 100,        frag = document.createDocumentFragment();    for (;i > 0; i--) {        p = document.createElement("p");        p.appendChild(document.createTextNode(i + " - "+ new Date().toTimeString()));        frag.appendChild(p);    }    document.getElementById("nodes").appendChild(frag);}function grow() {    x.push(new Array(1000000).join('x'));    createSomeNodes();    setTimeout(grow,1000);}


When grow is executed, create a p node and insert it into the DOM, and assign a huge array to the global variable. The tool mentioned above can detect a steady increase in memory.

Find the memory with a periodic increase
Timeline labels are good at doing this. Open The example in Chrome, open Dev Tools, switch to timeline, select memory, click record, and then click The Button on The page. After a while, stop the record and check the result:


  • Memory Management-Mozilla Developer Network

  • JScript Memory Leaks-Douglas Crockford (old, in relation to Internet Explorer 6 leaks)

  • JavaScript Memory Profiling-Chrome Developer Docs

  • Memory Diagnosis-Google Developers

  • An Interesting Kind of JavaScript Memory Leak-Meteor blog

  • Grokking V8 closures

The above are four types of JavaScript Memory leakage and how to avoid the content. For more information, see PHP Chinese Network (www.php1.cn )!

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.