In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "analyzing memory management in JS". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "analyzing memory management in JS".
Preface
Low-level languages like C generally have underlying memory management interfaces, such as malloc () and free () for allocating and freeing memory.
For JavaScript, memory is allocated when variables (objects, strings, etc.) are created, and memory is "automatically" freed when they are no longer used, a process called garbage collection.
Because of the existence of automatic garbage collection mechanism, most Javascript developers feel that they can not care about memory management, so it can lead to memory leaks in some cases.
Memory life cycle
The memory allocated in the JS environment has the following declaration cycle:
Memory allocation: when we declare variables, functions, and objects, the system automatically allocates memory for them
Memory usage: read and write memory, that is, using variables, functions, etc.
Memory collection: after use, the garbage collection mechanism automatically reclaims the memory that is no longer in use.
Memory allocation of JS
In order not to bother programmers to allocate memory, JavaScript completes memory allocation when defining variables.
Var n = 123; / assign memory to numeric variables var s = "azerty"; / / allocate memory to strings var = {a: 1, b: memory}; / / allocate memory to objects and the values they contain / / allocate memory to arrays and the values they contain (just like objects) var a = [1, null, "abra"]; function f (a) {return a + 2 } / / allocate memory to functions (callable objects) / / function expressions can also allocate an object someElement.addEventListener ('click', function () {someElement.style.backgroundColor =' blue';}, false)
Some function calls result in allocating object memory:
Var d = new Date (); / / assign a Date object var e = document.createElement ('div'); / / assign a DOM element
Some methods assign new variables or new objects:
Var s = "azerty"; var S2 = s.substr (0,3); / / S2 is a new string / / because the string is invariant, / / JavaScript may decide not to allocate memory, / / only stores the range of [0-3]. Var a = ["ouais ouais", "nan nan"]; var a2 = ["generation", "nan nan"]; var A3 = a.concat (a2); / / the new array has four elements, which is the result of a connecting a2.
Memory usage of JS
The process of using values is actually the operation of reading and writing to the allocated memory.
Reading and writing may be writing the property values of a variable or an object, or even passing the parameters of a function.
Var a = 10; / / allocate memory console.log (a); / / a pair of memory usage
Memory recovery of JS
JS has an automatic garbage collection mechanism, so what is the principle of this automatic garbage collection mechanism?
In fact, it is very simple to find those values that are no longer in use, and then free up the memory they occupy.
Most memory management problems are at this stage.
The hardest task here is to find variables that are no longer needed.
The variables that no longer need to be used, that is, the variables at the end of the life cycle, are local variables, and local variables only exist during the execution of the function.
When the function ends and there are no other references (closures), the variable is marked to recycle.
The life cycle of global variables does not end until the browser unloads the page, which means that global variables are not treated as garbage collection.
Because of the existence of automatic garbage collection mechanism, developers can not care about or pay attention to the problems related to memory release, but the release of useless memory is objective.
Unfortunately, current garbage collection algorithms cannot intelligently recycle all extreme cases, even without considering the impact of garbage collection on performance.
Next, let's explore the mechanism of JS garbage collection.
Garbage collection
Quote
Garbage collection algorithms mainly rely on the concept of references.
In a memory-managed environment, an object is called an object referencing another object if it has access to another object (implicitly or explicitly).
For example, a Javascript object has a reference to its prototype (implicit reference) and a reference to its properties (explicit reference).
Here, the concept of "object" refers not only to JavaScript objects, but also to functional scope (or global lexical scope).
Reference count garbage collection
This is the most basic garbage collection algorithm.
The reference counting algorithm defines the standard of "memory is no longer used", which is simply to see if an object has a reference to it.
If no other object points to it, the object is no longer needed.
Var o = {a: {BGV 2}}; / / two objects are created, one is referenced as an attribute of the other, and the other is assigned to the variable o / / obviously, no one can be garbage collected var O2 = o; / / O2 variable is the second reference to "this object" o = 1; / / now, the original reference o of "this object" has been replaced by O2 with var oa = o2.a. / / reference the a property of "this object" / / now, "this object" has two references, one is O2, the other is oa O2 = "yo"; / / the original object is now zero reference / / it can be garbage collected / / but its property an object is still referenced by oa, so oa = null cannot be recycled yet. The object with the / an attribute is now zero reference / / it can be garbage collected
As can be seen from the above, the reference counting algorithm is a simple and effective algorithm. But it has a fatal problem: circular references.
If two objects refer to each other, although they are no longer in use, garbage collection will not be reclaimed, resulting in a memory leak.
Let's look at an example of a circular reference:
Function f () {var o = {}; var O2 = {}; o.a = O2; / / o quote o2o2.a = o; / / O2 quote o here return "azerty";} f ()
Above we declare a function f that contains two objects that reference each other.
At the end of the call to the function, objects o1 and O2 are actually out of the scope of the function, so they are no longer needed.
However, according to the principle of reference counting, the mutual references between them still exist, so this part of the memory will not be reclaimed, and memory leaks are inevitable.
Let's look at a practical example:
Var div = document.createElement ("div"); div.onclick = function () {console.log ("click");}
The above JS writing is perfectly common, creating a DOM element and binding a click event.
At this point, the variable div has a reference to the event handler, and the event handler also has a reference to div! (the div variable can be accessed within the function).
A sequential reference appears, and according to the algorithm described above, this part of the memory is inevitably leaked.
In order to solve the problem caused by circular reference, modern browsers use tag removal algorithm to achieve garbage collection.
Label removal algorithm
The tag cleanup algorithm defines "objects that are no longer in use" as "unreachable objects".
To put it simply, it starts from the root (which is the global object in JS) and scans the objects in memory regularly.
All objects that can be reached from the root still need to be used.
Objects that cannot be reached from the root are marked as no longer in use and are recycled later.
From this concept, it can be seen that an unreachable object contains the concept of an object without a reference (an object without any reference is also an inaccessible object).
But the opposite may not be true.
Workflow:
The garbage collector marks all variables stored in memory at run time.
Clear the mark of the accessible object from the root.
Variables that still have tags are considered variables that are ready to be deleted.
The garbage collector performs an one-step memory cleanup, destroying those marked values and reclaiming the memory space they occupy.
Circular references are no longer a problem.
Take a look at the previous example of a circular reference:
Function f () {var o = {}; var O2 = {}; o.a = O2; / / o quote o2o2.a = o; / / O2 quote o return "azerty";} f ()
After the function call returns, the two circular referenced objects can no longer obtain their references from the global object during garbage collection.
Therefore, they will be recycled by the garbage collector.
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.
In essence, a memory leak is a waste of memory due to negligence or error that causes the program to fail to release memory that is no longer in use.
Identification method of memory leak
The rule of thumb is that if the memory footprint gets larger each time after five consecutive garbage collections, there will be a memory leak.
This requires a real-time view of memory usage.
In Chrome browsers, we can view the memory footprint like this
Open the developer tools and select the Performance panel
Check Memory at the top
Click the record button in the upper left corner
Perform various operations on the page to simulate the usage of users
After a period of time, click the stop button of the dialog box, and the panel will show the memory usage during that period.
Let's take a look at an effect picture:
There are two ways to determine if there is a current memory leak:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
After multiple snapshots, comparing the memory usage in each snapshot, if it shows an upward trend, then it can be considered that there is a memory leak.
After a snapshot, look at the current memory consumption trend chart, if the trend is not stable, showing an upward trend, then it can be considered that there is a memory leak
Use the process.memoryUsage method provided by Node to check memory in a server environment
Console.log (process.memoryUsage ()); / / {/ / rss: 27709440, / / heapTotal: 5685248, / / heapUsed: 3449392, / / external: 8772 / /}
Process.memoryUsage returns an object that contains the memory footprint information of the Node process.
The object contains four fields in bytes, meaning as follows:
Rss (resident set size): all memory footprint, including instruction area and stack.
HeapTotal: the memory used by the "heap", both used and unused.
HeapUsed: the part of the heap used.
External: memory consumed by C++ objects inside the V8 engine.
Determine the memory leak, based on the heapUsed field.
Common memory leak cases
Unexpected global variable
Function foo () {bar1 = 'some text'; / / No declaration variable is actually a global variable = > window.bar1 this.bar2 =' some text' / / global variable = > window.bar2} foo ()
In this example, two global variables bar1 and bar2 are created unexpectedly
Forgotten timers and callback functions
In many libraries, if the observer mode is used, callback methods are provided to call some callback functions.
Remember to recycle these callback functions. Take an example of setInterval:
Var serverData = loadData (); setInterval (function () {var renderer = document.getElementById ('renderer'); if (renderer) {render [XSS _ clean] = JSON.stringify (serverData);}}, 5000); / / call every 5 seconds
If the subsequent renderer element is removed, the entire timer actually has no effect.
But if you don't have a reclaim timer, the whole timer is still valid, not only the timer cannot be reclaimed by memory.
The dependencies in the timer function cannot be recycled. The serverData in this case cannot be recycled either.
Closure
In JS development, we often use closures, an internal function that has access to variables in the external function that contains it.
Closures can also cause memory leaks in the following cases:
Var theThing = null; var replaceThing = function () {var originalThing = theThing; var unused = function () {if (originalThing) / / reference to 'originalThing' console.log ("hi"); theThing = {longStr: new Array (1000000). Join (' *'), someMethod: function () {console.log ("message");}; setInterval (replaceThing, 1000)
In this code, each time replaceThing is called, theThing gets an object containing a large array and an object for the new closure someMethod.
At the same time, unused is a closure that references originalThing.
The key to this example is that closures share scope, and although unused may never be called, someMethod may be called, resulting in a failure to reclaim its memory.
When this code is executed repeatedly, memory continues to grow.
DOM reference
Most of the time, when we operate on Dom, we save the reference to Dom in an array or Map.
Var elements = {image: document.getElementById ('image')}; function doStuff () {elements.image.src =' http://example.com/image_name.png';} function removeImage () {document.body.removeChild (document.getElementById ('image')); / / at this time we still have a reference to # image, the Image element, which still cannot be reclaimed by memory. }
In the above case, even though we have removed the image element, there is still a reference to the image element and memory collection is still not possible for alignment.
Another point to note is the reference to the leaf node of an Dom tree.
For example: if we refer to a td element in a table, once the entire table is deleted in Dom, we intuitively feel that memory recycling should recycle elements other than the referenced td.
But in fact, this td element is a child of the entire table and retains a reference to its parent element.
This results in no memory collection for the entire table. So we have to be careful with references to Dom elements.
How to avoid memory leaks
Remember one principle: return what you don't need in time.
Reduce unnecessary global variables and use strict mode to avoid accidental creation of global variables.
After you have finished using the data, dereferencing in time (variables in closures, dom references, timer clearing).
Organize your logic to avoid problems such as endless loops that cause browsers to stutter and crash.
Thank you for reading, the above is the content of "analyzing memory management in JS". After the study of this article, I believe you have a deeper understanding of the analysis of memory management in JS, 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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.