Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

An example Analysis of JavaScript memory leak

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains the "JavaScript memory leak case analysis", the content of the article is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "JavaScript memory leak case analysis"!

Js memory leak what is a memory leak?

The program needs memory to run. The operating system or runtime (runtime) must provide memory whenever the program requests it.

For continuously running service processes (daemon), memory that is no longer used must be released in a timely manner. Otherwise, the memory footprint is getting higher and higher, which will affect the system performance and cause the process to crash.

Memory that is no longer used and is not released in time is called a memory leak.

Some languages, such as C, must release memory manually, and programmers are responsible for memory management.

Char* buffer;buffer = (char*) malloc (42) / / Do something with bufferfree (buffer)

The above is the C language code, the malloc method is used to apply for memory, after the use, you must use the free method to release the memory.

This is troublesome, so most languages provide automatic memory management to lighten the burden on programmers, which is called the "garbage collection mechanism" (garbage collector).

Although there is a garbage collection mechanism at the front end, a memory leak occurs when a piece of useless memory cannot be considered garbage by the garbage collection mechanism.

What conditions can cause memory leaks

1. Unexpected global variable

The global variable has the longest life cycle and survives until the page is closed, so the memory on the global variable is never reclaimed.

Memory leaks occur when global variables are improperly used, not reclaimed in time (manual assignment null), or when a variable is mounted to a global variable by misspelling.

two。 Forgotten timer

SetTimeout and setInterval are maintained by browser-specific threads, so when timers are used on a page and when the page is destroyed, these timers are still alive without manually releasing and cleaning them.

That is to say, the life cycle of the timer is not attached to the page, so when a callback function is registered in the js of the current page through a timer, and the callback function holds a variable or some DOM elements of the current page, it will cause even if the page is destroyed, the page cannot be reclaimed normally because the timer holds a partial reference to the page, resulting in a memory leak.

If you open the same page again at this time, there are actually two pages of data in memory. If you close and open it many times, the memory leak will become more and more serious. And this scenario is easy to happen, because people who use timers are easy to forget and erase.

3. Improper closure

The function itself holds a reference to the lexical environment in which it was defined, but usually, after using the function, the memory requested by the function will be reclaimed.

However, when another function is returned within the function, because the returned function holds the lexical environment of the external function, and the returned function is held by other life cycle things, although the external function is executed, the memory can not be reclaimed.

4. Missing DOM element

The life cycle of the DOM element normally depends on whether it is mounted on the DOM tree. When it is removed from the DOM tree, it can be destroyed and recycled.

But if a DOM element also holds its reference in js, its life cycle is determined by both js and whether it is on the DOM tree. Remember to remove it in both places that need to be cleaned in order to recycle it properly.

5. Network callback

In some scenarios, if a network request is initiated on a page and a callback is registered, and some content of the page is held in the callback function, then when the page is destroyed, the callback of the network should be logged out, otherwise, because the network holds part of the content of the page, it will also cause part of the content of the page to not be recycled.

How to monitor memory leaks

Memory leaks can be divided into two categories, one is more serious, the leaked ones can not be recovered all the time, and the other is slightly less serious, that is, the memory leaks caused by failure to clean up in time can still be cleaned up after a period of time.

Either way, the memory map captured by the developer's tools should see a continuous linear decline in memory footprint over a period of time, due to the constant occurrence of GC, that is, garbage collection.

Insufficient memory will cause continuous GC, while GC will block the main thread, so it will affect page performance and cause stutters, so memory leaks still need to be concerned.

Scenario 1: apply for a piece of memory in a function, and then the function is called continuously in a short period of time.

/ / Click the button, execute the function once, and apply for a memory startBtn.addEventListener ("click", function () {var a = new Array (100000) .fill (1); var b = new Array (20000) .fill (1);})

The amount of memory that a page can use is limited, and when it runs out of memory, it triggers a garbage collection mechanism to reclaim useless memory.

The variables used inside the function are all local variables, and after the function is executed, this piece of memory is useless and can be reclaimed.

So when we keep calling the function in a short period of time, we can find that there is not enough memory when the function is executed, and the garbage collection mechanism works to reclaim the memory requested by the last function, because the last function has been executed. Memory is useless and can be reclaimed.

So the chart showing memory usage in the chart is a horizontal line, and there are many vertical lines in the middle, which actually means that the memory is empty, and then apply, and then apply. The position of each vertical bar is the time for garbage collection mechanism to work and function execution to apply again.

Scenario 2: apply a piece of memory in a function, and then the function is called continuously in a short period of time, but part of the memory applied for each time is held externally.

/ / Click the button to execute the function once and apply for a piece of memory var arr = []; startBtn.addEventListener ("click", function () {var a = new Array (100000) .fill (1); var b = new Array (20000) .fill (1); arr.push (b);})

What's the difference between it and the first picture?

It is no longer a horizontal line, and the bottom of each vertical line in the horizontal line is not the same level.

Actually, this is a memory leak.

We apply for two array memory in the function, but one of the array is held externally, so even after each execution of the function, the externally held array memory still cannot be reclaimed, so only part of the memory can be reclaimed at a time.

In this way, when the number of function calls increases, the more memory that cannot be reclaimed and the more memory leaks, resulting in a continuous increase in memory usage.

In addition, you can also use the performance monitor tool to find more buttons in the developer's tool and open this function panel. This is a tool that can monitor the usage of cpu, memory, and so on in real time, and it will be more intuitive than the tool that can only be captured for a period of time:

The ladder is the occurrence of memory leakage, each function call, there is always a part of the data held externally so that it can not be recycled, and the later smooth is that it can be recovered normally every time it is used.

This picture should be noted that there is a straight slide at the end of the first red box, this is because I modified the code to remove the line of code applied for in the external holding function, and then refreshed the page and manually clicked GC to trigger the effect, otherwise, no matter how you click GC, some memory has been unable to recover, can not achieve such an effect.

The above are some tools to monitor whether memory leaks occur, but the next step is the key. Now that memory leaks are found, how to locate them? How do you know which part of the data was not recycled and caused the leak?

How to analyze memory leaks and find problematic code

To analyze the causes of memory leaks, you still need to use the Memory feature of developer tools, which can capture memory snapshots, memory allocation over a period of time, and functions that trigger memory allocation over a period of time.

Using these tools, we can analyze which function operation leads to memory allocation at some point, and what are a large number of repetitive objects that have not been recycled.

In this way, the suspected function also knows, the suspected object also knows, and then go to the code to analyze whether the object in this function is the culprit of the memory leak.

Let's give a simple example, and then an example of an actual memory leak:

Scenario 1: apply for a piece of memory in a function, and then the function is called continuously in a short period of time, but part of the memory requested each time is held externally.

/ / A portion of the memory cannot be reclaimed every time the button is clicked, because the external arr holds var arr = []; startBtn.addEventListener ("click", function () {var a = new Array (100000) .fill (1); var b = new Array (20000) .fill (1); arr.push (b);})

You can take two snapshots, perform a memory leak operation between them, and finally compare the difference between the two snapshots to see what the added objects are and what the recycled objects are, as shown in the figure above.

You can also view the snapshot at a certain time separately to see what objects occupy a lot of memory from the memory footprint ratio, as shown below:

From the perspective of garbage collection mechanism, you can also see which of the reachable objects from the GC root root node take up a lot of memory:

Starting with the above methods, you can see what the object that currently takes up a lot of memory is. Generally speaking, this is the suspect.

Of course, not necessarily. When there is a suspect, you can use multiple memory snapshot comparisons to manually force GC in the middle to see if the object has been recycled. This is a way of thinking.

Crawl for a period of time, memory allocation.

In this way, you can selectively see which function initiates each memory allocation and what objects are stored in memory.

Of course, memory allocation is normal behavior, and you need to use other data to determine whether an object is suspected, such as memory footprint, or combined with memory snapshots, and so on.

Grab the memory usage of the function over a period of time

This can see very little, relatively simple, the purpose is also very clear, that is, over a period of time, what operations are applying for memory, and how much is used.

In short, these tools have no way to give you a direct answer, telling you that xxx is the culprit of the memory leak. If you can determine it at the browser level, why doesn't it recycle it? why does it cause the memory leak?

Therefore, these tools can only give you all kinds of memory usage information, and you need to use this information to analyze which suspected objects are the culprits of memory leaks according to the logic of your own code.

Case analysis

Example 1:

Var t = null;var replaceThing = function () {var o = t var unused = function () {if (o) {console.log ("hi")} t = {longStr: new Array (100000). Fill ('*'), someMethod: function () {console.log (1)}} setInterval (replaceThing, 1000)

First talk about the purpose of the code, declare a global variable t and a replaceThing function, the purpose of the function is to assign a new object to the global variable, and then there is an internal variable to store the value before the global variable t is replaced, and finally the timer periodically executes the replaceThing function

Find a problem

Let's first use the tool to see if there is a memory leak:

Three kinds of memory monitoring charts show that there is a memory leak: repeated execution of the same function, memory ladder growth, manual click on GC memory has not decreased, indicating that there is a partial memory leak each time the function is executed.

This manual forced garbage collection can not keep the memory down is very serious, long-term implementation, will run out of available memory, resulting in page stutters or even collapse.

Analyze the problem

Now that a memory leak has been identified, it's time to find out the cause of the memory leak.

First of all, through sampling profile, we locate the suspect to the function replaceThing.

Next, let's take two memory snapshots and compare them to see if we can get any information:

Comparing the two snapshots, you can see that the array object has been increasing along the way, and the array object comes from the longStr property of the object created inside the replaceThing function.

In fact, there is a lot of information in this picture, especially in the nesting diagram below, where the nesting relationship is reversed. If you look at it backwards, you can see how the global object Window accesses the array object step by step. Garbage collection mechanism cannot be recycled because of such an accessible access path.

In fact, it can be analyzed here, in order to use more tools, let's change the diagram to analyze it.

Let's start directly with the second memory snapshot and take a look:

Why can't internally created objects be recycled after each replaceThing function call?

Because of the first creation of replaceThing, this object is held by the global variable t, so it cannot be recycled.

With each subsequent call, this object is held by the o local variable inside the previous replaceThing function and cannot be recycled.

The local variable o in this function is held by the someMethod method of the object created when replaceThing is first called, and the object mounted by this method is held by the global variable t, so it cannot be recycled.

In this way, each function call will hold the local variables created internally when the function is last called, so that even if the function execution ends, these local variables cannot be recovered.

Thank you for your reading, the above is the content of "JavaScript memory leak instance Analysis". After the study of this article, I believe you have a deeper understanding of the problem of JavaScript memory leak instance analysis, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report