Home Web Front-end JS Tutorial JavaScript also talks about memory optimization_javascript skills

JavaScript also talks about memory optimization_javascript skills

May 16, 2016 pm 04:45 PM
javascript Memory optimization

Compared to C/C, the memory processing of JavaScript we use has allowed us to pay more attention to the writing of business logic during development. However, with the continuous complexity of business and the development of single-page applications, mobile HTML5 applications, Node.js programs, etc., phenomena such as lagging and memory overflow caused by memory problems in JavaScript are no longer unfamiliar.

This article will discuss memory usage and optimization from the language level of JavaScript. From the aspects that everyone is familiar with or have heard a little about, to the areas that most people don’t notice, we will analyze them one by one.

1. Language-level memory management

1.1 Scope

Scope is a very important operating mechanism in JavaScript programming. In synchronous JavaScript programming, it does not fully attract the attention of beginners, but in asynchronous programming, good scope control skills become the key to JavaScript development. Required skills for operators. Additionally, scope plays a crucial role in JavaScript memory management.

In JavaScript, the scopes can be formed by function calls, with statements and global scope.

Take the following code as an example:

Copy the code The code is as follows:

var foo = function() {
var local = {};
};
foo();
console.log(local); //=> undefined

var bar = function() {
local = {};
};
bar();
console.log(local); //=> {}

Here we define the foo() function and the bar() function. Their intention is to define a variable named local. But the end result was completely different.

In the foo() function, we use the var statement to declare and define a local variable. Since a scope will be formed inside the function body, this variable is defined in the scope. Moreover, the body of the foo() function does not do any scope extension processing, so after the function is executed, the local variable is also destroyed. The variable cannot be accessed in the outer scope.

In the bar() function, the local variable is not declared using the var statement. Instead, local is defined directly as a global variable. Therefore, the outer scope can access this variable.

Copy code The code is as follows:

local = {};
// here The definition is equivalent to
global.local = {};


1.2 Scope Chain

In JavaScript programming, you will definitely When encountering a scenario with multiple levels of function nesting, this is the representation of a typical scope chain.

As shown in the following code:

Copy the code The code is as follows:

function foo( ) {
var val = 'hello';

function bar() {
function baz() {
global.val = 'world;'
}
baz ();
console.log(val); //=> hello
}
bar();
}
foo();

Based on the previous description of scope, you may think that the result displayed by the code here is world, but the actual result is hello. Many beginners will start to get confused here, so let's take a look at how this code works.

Because in JavaScript, the search for variable identifiers starts from the current scope and searches outward until the global scope. Therefore, access to variables in JavaScript code can only be done outward, not the other way around.

JavaScript also talks about memory optimization_javascript skills

The execution of the baz() function defines a global variable val in the global scope. In the bar() function, when accessing the identifier val, the search principle is from inside to outside: if it is not found in the scope of the bar function, it goes to the upper level, that is, the scope of the foo() function. Search in scope.

However, the key to making everyone confused is here: this identifier access finds a matching variable in the scope of the foo() function, and will not continue to search outwards, so in the baz() function The defined global variable val has no impact on this variable access.

1.3 Closure

We know that identifier lookup in JavaScript follows the inside-out principle. However, with the complexity of business logic, a single delivery sequence is far from meeting the increasing new needs.

Let’s take a look at the following code first:

Copy the code The code is as follows:

function foo() {
var local = 'Hello';
return function() {
return local;
};
}
var bar = foo();
console.log(bar()); //=> Hello

The technology shown here to allow the outer scope to access the inner scope is closure (Closure). Thanks to the application of higher-order functions, the scope of the foo() function has been "extended".

The foo() function returns an anonymous function, which exists in the scope of the foo() function, so you can access the local variable in the scope of the foo() function and save its reference. Since this function directly returns the local variable, the bar() function can be directly executed in the outer scope to obtain the local variable.

Closure is an advanced feature of JavaScript. We can use it to achieve more complex effects to meet different needs. However, it should be noted that because the function with internal variable references is taken out of the function, the variables in the scope will not necessarily be destroyed after the function is executed until all references to the internal variables are released. Therefore, the application of closures can easily cause memory to be unable to be released.

2. JavaScript memory recycling mechanism

Here I will take the V8 engine launched by Google used by Chrome and Node.js as an example to briefly introduce the memory recycling mechanism of JavaScript. For more detailed content, you can purchase my good friend Pu Ling’s book "Speaking in Simple and Deep Language" Node.js" to learn, in which the chapter "Memory Control" has a quite detailed introduction.

In V8, all JavaScript objects are allocated memory through the "heap".

JavaScript also talks about memory optimization_javascript skills

When we declare a variable in the code and assign a value, V8 will allocate a part of the heap memory to the variable. If the allocated memory is not enough to store this variable, V8 will continue to apply for memory until the heap size reaches the V8 memory limit. By default, the upper limit of V8's heap memory size is 1464MB in 64-bit systems and 732MB in 32-bit systems, which is about 1.4GB and 0.7GB.

In addition, V8 manages JavaScript objects in heap memory by generation: new generation and old generation. The new generation refers to JavaScript objects with a short life cycle, such as temporary variables, strings, etc.; while the old generation refers to objects that have survived multiple garbage collections and have a long life cycle, such as main controllers, server objects, etc.

Garbage collection algorithms have always been an important part of the development of programming languages, and the garbage collection algorithms used in V8 mainly include the following:

1. Scavange algorithm: memory space management through copying, mainly used for the memory space of the new generation;
2. Mark-Sweep algorithm and Mark-Compact algorithm: organize and organize the heap memory through marking Recycling is mainly used for inspection and recycling of old generation objects.


PS: More detailed V8 garbage collection implementation can be learned by reading relevant books, documents and source code.

Let’s take a look at which objects the JavaScript engine will recycle under what circumstances.

2.1 Scope and Reference

Beginners often mistakenly believe that when the function completes execution, the object declared inside the function will be destroyed. But in fact, this understanding is not rigorous and comprehensive, and it can easily lead to confusion.

Reference is a very important mechanism in JavaScript programming, but the strange thing is that most developers don’t pay attention to it or even understand it. Reference refers to the abstract relationship of "code's access to objects". It is somewhat similar to C/C pointers, but they are not the same thing. References are also the most critical mechanism for garbage collection by the JavaScript engine.

Take the following code as an example:

Copy the code The code is as follows:

// . .....
var val = 'hello world';
function foo() {
return function() {
return val;
};
}
global.bar = foo();
// ......

After reading this code, can you tell which objects are still alive after this part of the code is executed?

According to relevant principles, the objects in this code that have not been recycled include val and bar(). What is the reason why they cannot be recycled?

How does the JavaScript engine perform garbage collection? The garbage collection algorithm mentioned earlier is only used during recycling, so how does it know which objects can be recycled and which objects need to continue to survive? The answer is a reference to a JavaScript object.

In JavaScript code, even if you simply write a variable name as a separate line without doing any operation, the JavaScript engine will think that this is an access behavior to the object, and there is a reference to the object. In order to ensure that the behavior of garbage collection does not affect the operation of program logic, the JavaScript engine must not recycle the objects being used, otherwise it will be chaotic. So the criterion for judging whether an object is in use is whether there is still a reference to the object. But in fact, this is a compromise, because JavaScript references can be transferred, then some references may be brought to the global scope, but in fact there is no need to modify them in the business logic. Once accessed, it should be recycled, but the JavaScript engine will still rigidly believe that the program still needs it.

How to use variables and references in the correct manner is the key to optimizing JavaScript from the language level.

3. Optimize your JavaScript

Finally getting to the point. Thank you very much for your patience in reading this. After all the above introductions, I believe you already have a good understanding of JavaScript’s memory management mechanism. Then the following techniques will make you even more powerful.

3.1 Make good use of functions

If you have the habit of reading excellent JavaScript projects, you will find that when many experts develop front-end JavaScript code, they often use an anonymous function to wrap the outermost layer of the code.

Copy code The code is as follows:

(function() {
// Main business Code
})();

Some are even more advanced:
Copy code The code is as follows :

;(function(win, doc, $, undefined) {
// Main business code
})(window, document, jQuery);

Even front-end modular loading solutions such as RequireJS, SeaJS, OzJS, etc. adopt a similar form:
Copy code Code As follows:

// RequireJS
define(['jquery'], function($) {
// Main business code
});

// SeaJS
define('module', ['dep', 'underscore'], function($, _) {
// Main business code
});

If you say that the code of many Node.js open source projects is not handled in this way, then you are wrong. Before actually running the code, Node.js will package each .js file into the following form:
Copy code The code is as follows:

(function(exports, require, module, __dirname, __filename) {
// Main business code
});

What are the benefits of doing this? We all know that as mentioned at the beginning of the article, the scopes in JavaScript include function calls, with statements and global scope. And we also know that objects defined in the global scope are likely to survive until the process exits. If it is a large object, it will be troublesome. For example, some people like to do template rendering in JavaScript:

Copy the code The code is as follows:
 
  $db = mysqli_connect(server, user, password, 'myapp');
  $topics = mysqli_query($db, "SELECT * FROM topics;");
?>



 
  你是猴子请来的逗比么?


 

     
     

    这种代码在新手的作品中经常能看得到,这里存在什么问题呢?如果在从数据库中获取到的数据的量是非常大的话,前端完成模板渲染以后,data变量便被闲置在一边。可因为这个变量是被定义在全局作用域中的,所以JavaScript引擎不会将其回收销毁。如此该变量就会一直存在于老生代堆内存中,直到页面被关闭。

    可是如果我们作出一些很简单的修改,在逻辑代码外包装一层函数,这样效果就大不同了。当UI渲染完成之后,代码对data的引用也就随之解除,而在最外层函数执行完毕时,JavaScript引擎就开始对其中的对象进行检查,data也就可以随之被回收。

    3.2 绝对不要定义全局变量

    我们刚才也谈到了,当一个变量被定义在全局作用域中,默认情况下JavaScript 引擎就不会将其回收销毁。如此该变量就会一直存在于老生代堆内存中,直到页面被关闭。

    那么我们就一直遵循一个原则:绝对不要使用全局变量。虽然全局变量在开发中确实很省事,但是全局变量所导致的问题远比其所带来的方便更严重。

    使变量不易被回收;
    1.多人协作时容易产生混淆;
    2.在作用域链中容易被干扰。
    3.配合上面的包装函数,我们也可以通过包装函数来处理『全局变量』。

    3.3 手工解除变量引用

    如果在业务代码中,一个变量已经确切是不再需要了,那么就可以手工解除变量引用,以使其被回收。

    复制代码 代码如下:

    var data = { /* some big data */ };
    // blah blah blah
    data = null;

    3.4 善用回调

    除了使用闭包进行内部变量访问,我们还可以使用现在十分流行的回调函数来进行业务处理。

    复制代码 代码如下:

    function getData(callback) {
    var data = 'some big data';

    callback(null, data);
    }

    getData(function (err, data) {
    console.log(data);

    The callback function is a Continuation Passing Style (CPS) technology. This style of programming shifts the business focus of the function from the return value to the callback function. And it has many advantages over closures:

    1. If the parameters passed in are basic types (such as strings, numeric values), the formal parameters passed in the callback function will be copied values. After the business code is used, it is easier to recycle;
    2 .Through callbacks, in addition to completing synchronous requests, we can also use it in asynchronous programming, which is a very popular writing style now;
    3. The callback function itself is usually a temporary anonymous function. Once requested After the function is executed, the reference of the callback function itself will be released and itself will be recycled.

    3.5 Good closure management

    When our business requirements (such as loop event binding, private properties, parameter-containing callbacks, etc.) must use closures, please be careful about the details.

    Loop binding events can be said to be a required course for getting started with JavaScript closures. We assume a scenario: there are six buttons, corresponding to six types of events. When the user clicks the button, the corresponding event is output at the specified place.


    Copy code The code is as follows:

    var btns = document.querySelectorAll('. btn'); // 6 elements
    var output = document.querySelector('#output');
    var events = [1, 2, 3, 4, 5, 6];

    // Case 1
    for (var i = 0; i < btns.length; i ) {
    btns[i].onclick = function(evt) {
    output.innerText = 'Clicked ' events [i];
    };
    }

    // Case 2
    for (var i = 0; i < btns.length; i ) {
    btns[i] .onclick = (function(index) {
    return function(evt) {
    output.innerText = 'Clicked ' events[index];
    };
    })(i);
    }

    // Case 3
    for (var i = 0; i < btns.length; i ) {
    btns[i].onclick = (function(event) {
    return function(evt) {
           output.innerText = 'Clicked ' event;
        };
       })(events[i]);
    }

    The first solution here is obviously a typical loop binding event error. I won’t go into details here. For details, you can refer to the answer I gave to a netizen; and the difference between the second and third solutions lies in the incoming closure. parameters.

    The parameter passed in in the second solution is the current loop subscript, while the latter directly passes in the corresponding event object. In fact, the latter is more suitable for large-scale data applications, because in JavaScript functional programming, the parameters passed in when the function is called are basic type objects, so the formal parameters obtained in the function body will be a copied value, so This value is defined as a local variable in the scope of the function body. After completing the event binding, the events variable can be manually dereferenced to reduce the memory usage in the outer scope. And when an element is deleted, the corresponding event listening function, event object, and closure function are also destroyed and recycled.

    3.6 Memory is not a cache

    Caching plays an important role in business development and can reduce the burden of time and space resources. But it should be noted that do not use memory as a cache easily. Memory is a valuable resource for any program development. If it is not a very important resource, please do not place it directly in the memory, or develop an expiration mechanism to automatically destroy the expired cache.

    4. Check JavaScript memory usage

    In daily development, we can also use some tools to analyze and troubleshoot memory usage in JavaScript.

    4.1 Blink / Webkit Browser

    In Blink/Webkit browsers (Chrome, Safari, Opera etc.), we can use the Profiles tool of Developer Tools to check the memory of our program.

    JavaScript also talks about memory optimization_javascript skills
    4.2 Memory Checking in Node.js

    In Node.js, we can use node-heapdump and node-memwatch modules for memory checking.

    Copy code The code is as follows:

    var heapdump = require('heapdump');
    var fs = require('fs');
    var path = require('path');
    fs.writeFileSync(path.join(__dirname, 'app.pid'), process.pid);
    // ...

    複製程式碼 代碼如下:
    ', 'Bitstream Charter', Times, serif; font-size: 14px; line-height: 1.5em;">在業務程式碼中引入node-heapdump 之後,我們需要在某個運行時期,向Node.js 進程發送SIGUSR2 訊號,讓node-heapdump 抓拍一份堆記憶體的快照。
    程式碼如下:
    $ kill -USR2 (cat app. pid)

    這樣在文件目錄下會有一個以heapdump-..heapsnapshot格式命名的快照文件,我們可以使用瀏覽器的Developer Tools中的Profiles工具將其打開,並進行檢查。

    5. 小結

    很快又來到了文章的結束,這篇分享主要向大家展示了以下幾點內容:


    1.JavaScript 在語言層面上,與記憶體使用息息相關的東西;
    2.JavaScript 中的記憶體管理、回收機制;
    3.如何更有效率地使用內存,以至於讓出產的JavaScript能更有拓展的活力;

    4.如何在遇到記憶體問題的時候,進行記憶體檢查。


    希望透過這篇文章的學習,你能夠出產更優秀的JavaScript 程式碼,讓媽媽安心、讓老闆放心。

    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    C++ memory optimization techniques revealed: key methods to reduce memory usage C++ memory optimization techniques revealed: key methods to reduce memory usage Nov 27, 2023 am 11:36 AM

    C++ is an efficient and powerful programming language, but when processing large-scale data or running complex programs, memory optimization becomes an issue that developers cannot ignore. Properly managing and reducing memory usage can improve program performance and reliability. This article will reveal some key tips for reducing memory footprint in C++ to help developers build more efficient applications. Use appropriate data types In C++ programming, choosing the appropriate data type is an important step in reducing memory usage. For example, if you only need to represent a small range of integers, you can use

    How to implement an online speech recognition system using WebSocket and JavaScript How to implement an online speech recognition system using WebSocket and JavaScript Dec 17, 2023 pm 02:54 PM

    How to use WebSocket and JavaScript to implement an online speech recognition system Introduction: With the continuous development of technology, speech recognition technology has become an important part of the field of artificial intelligence. The online speech recognition system based on WebSocket and JavaScript has the characteristics of low latency, real-time and cross-platform, and has become a widely used solution. This article will introduce how to use WebSocket and JavaScript to implement an online speech recognition system.

    WebSocket and JavaScript: key technologies for implementing real-time monitoring systems WebSocket and JavaScript: key technologies for implementing real-time monitoring systems Dec 17, 2023 pm 05:30 PM

    WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

    How to use JavaScript and WebSocket to implement a real-time online ordering system How to use JavaScript and WebSocket to implement a real-time online ordering system Dec 17, 2023 pm 12:09 PM

    Introduction to how to use JavaScript and WebSocket to implement a real-time online ordering system: With the popularity of the Internet and the advancement of technology, more and more restaurants have begun to provide online ordering services. In order to implement a real-time online ordering system, we can use JavaScript and WebSocket technology. WebSocket is a full-duplex communication protocol based on the TCP protocol, which can realize real-time two-way communication between the client and the server. In the real-time online ordering system, when the user selects dishes and places an order

    How to implement an online reservation system using WebSocket and JavaScript How to implement an online reservation system using WebSocket and JavaScript Dec 17, 2023 am 09:39 AM

    How to use WebSocket and JavaScript to implement an online reservation system. In today's digital era, more and more businesses and services need to provide online reservation functions. It is crucial to implement an efficient and real-time online reservation system. This article will introduce how to use WebSocket and JavaScript to implement an online reservation system, and provide specific code examples. 1. What is WebSocket? WebSocket is a full-duplex method on a single TCP connection.

    JavaScript and WebSocket: Building an efficient real-time weather forecasting system JavaScript and WebSocket: Building an efficient real-time weather forecasting system Dec 17, 2023 pm 05:13 PM

    JavaScript and WebSocket: Building an efficient real-time weather forecast system Introduction: Today, the accuracy of weather forecasts is of great significance to daily life and decision-making. As technology develops, we can provide more accurate and reliable weather forecasts by obtaining weather data in real time. In this article, we will learn how to use JavaScript and WebSocket technology to build an efficient real-time weather forecast system. This article will demonstrate the implementation process through specific code examples. We

    Simple JavaScript Tutorial: How to Get HTTP Status Code Simple JavaScript Tutorial: How to Get HTTP Status Code Jan 05, 2024 pm 06:08 PM

    JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

    How to use insertBefore in javascript How to use insertBefore in javascript Nov 24, 2023 am 11:56 AM

    Usage: In JavaScript, the insertBefore() method is used to insert a new node in the DOM tree. This method requires two parameters: the new node to be inserted and the reference node (that is, the node where the new node will be inserted).

    See all articles