Home  >  Article  >  Web Front-end  >  Detailed explanation of Nodejs memory management steps

Detailed explanation of Nodejs memory management steps

php中世界最好的语言
php中世界最好的语言Original
2018-05-22 09:21:101473browse

This time I will bring you a detailed explanation of the steps of Nodejs memory management. What are the precautions for Nodejs memory management? The following is a practical case, let's take a look.

sThe running host environment is different, and the corresponding requirements for memory management are also different. When the host environment is a browser, because the running time of the web page is short and it only runs on the user's machine (equivalent to Distributed), even if the memory is used too much or there is a certain memory leak, it will not have much impact on the end user. When the host environment is used to program the server (Node), the situation is quite different. The code itself runs on a few fixed machines (centralized), and the running time is a long time. Once the memory management is not good, memory expansion will occur. Even if there is a memory leak, the server-side response time will become longer or even the service will crash.

Nodejs is built based on V8, so the

JavaScript objects used in Node (Buffer is not) are basically allocated and managed through V8. V8 places limits on the memory size it occupies (for a 64-bit operating system, the maximum heap memory size that can be used by a single Node process is approximately 1.5GB). Even if the server has a large memory, Node cannot fully utilize the server's resources due to this limitation of V8. Even so, why does V8 have such restrictions? The reason for this restriction is actually related to the garbage collection mechanism. Taking the 1.5GB garbage collection heap memory heap as an example, V8 takes more than 50ms to do a small garbage collection, and even takes more than 1s to do a full garbage collection. You must know the garbage During the recycling process, the JavaScript thread must be in a suspended state. Too long a temporary time will have a great impact on the performance of the back-end service. Therefore, for this reason, V8 has limits on the heap memory. Even so, V8 still provides a way to customize the heap memory size (--max-old-pace-size). old-space represents the old generation and new-space represents the new generation.

node --max-old-space-size=xxx index.js //单位为MB
// 之前还可以通过-max-new-space-size来定义新生代堆大小,现在已经不可以了
When the server restarts frequently due to memory leaks, it is recommended to increase the heap memory size first to buy time to locate the problem. After all, a slow service response is better for users than returning an error page directly. Accept it a little bit.

Why do we need the old generation and the new generation?

The old generation and the new generation are actually different generations in the generational garbage collection mechanism, because no garbage collection algorithm can be qualified for all scenarios, and different object life cycles actually require different The best recycling strategy can achieve the best results, so V8 adopts a generational garbage collection mechanism, which divides objects into different generations according to their survival time, and then applies more suitable methods to the memory of different generations (new generation, old generation). Also a better algorithm.

Objects in the new generation have a shorter survival time, while objects in the old generation have a longer survival time or even reside in memory. The memory of the new generation designed based on this is generally much smaller than the memory of the old generation. The maximum memory of the new generation in V8 is 32M (64-bit system as an example), and the maximum memory of the old generation is 1400MB. The actual heap memory size used by V8 is the sum of the memory used by the new generation and the old generation (1432MB), but the maximum value of V8 is actually 32M (1464MB) larger than the used memory pair size

New Generation How to do garbage collection?

The new generation uses a garbage collection algorithm called Scavenge. In the specific implementation of Scavenge, the Cheney algorithm is mainly used. The Cheney algorithm divides the new generation heap into two, one is used (From semispace) and the other is free (To semispace).

When creating an object, it is now allocated in the From space. When garbage collection is required, the surviving objects in the From space are checked, and then the surviving objects are copied to the To space, and the From space is cleared at the same time. By exchanging From and To, the entire garbage collection process is to copy the surviving objects between the two seispaces. For lifecycleshort scenarios, the surviving objects account for a relatively small proportion of the entire object, so Scavenge uses copying of the surviving objects, but Scavenge can only use half of the heap memory space. This is a typical space swap. The embodiment of time.

当一个对象经过多次垃圾回收依然存活的话,就会被认为是生命周期较长的对象,一方面新生代堆比较小,另一方面重复复制生命周期长的对象也很没有效率,所以对于生命周期长的对象会被移到老生代中去。新生代对象移动到老生代有两个对象:1.对象是否是生命周期较长的对象(已经经历过垃圾回收)2.To空间使用占比是否超过了25%。限制25%的原因是由于垃圾回收完成后To会变成From,如果不做限制的话可能会出现From很快被用光的情况,出现频繁的垃圾回收,也会影响效率。

老生代如何做垃圾回收?

老生代由于存活对象占较大比重,不适合对存活对象进行操作,使用Scavenge算法就不太合适了,因此老生代采用了Mark-Sweep和Mark-Compact相结合的方式。

Mark-Sweep分为标记和清除两个阶段,在标记阶段遍历堆中所有对象,标记活着的对象,然后在清除阶段未被标记的对象将会被清除掉。Mark-Sweep解决了内存释放的问题但是由于没有像Scavenge那样复制对象的操作导致内存碎片化不连续。而Mark-Compact就是用来解决内存碎片化问题的。Mark-Compact会将存活的对象往一端移动,移动完成后直接清理掉边界外的内存,这样就有大段的连续可用内存了,但是由于涉及到对象的移动,因此Mark-Compact的速度要比Mark-Sweep慢了。V8主要使用Mark-Sweep,只有当空间不足以对新生代中今生过来的对象进行分配时才使用Mark-Compact。

垃圾回收过程中会导致应用程序暂停执行,由于新生代本身空间较小,且要复制的存活对象占比也少,因此即便执行全量垃圾回收也影响不大,但是老生代空间很大,存活对象也多,执行一次全量垃圾回收对于应用程序暂停会是一个比较长的时间,因此V8将老生的标记改成了增量更新的方式,使得标记和应用程序交替执行直到标记完成,然后垃圾回收再执行后面的清理工作。注意清理工作并不是增量的。

开发者可以指定强制垃圾回收吗?

答案是可以了,在启动node服务的时候使用--expose-gc flag

$ node --expose-gc file.js

这样全局对象上就有了执行垃圾回收的函数

global.gc();

推荐更安全的写法

function forceGC()
 if (global.gc) {
  global.gc();
 } else {
  console.warn('No GC hook! Start your program as `node --expose-gc file.js`.');
 }
}

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Vue页面骨架屏注入步骤详解

解决node修改后需频繁手动重启如何处理

The above is the detailed content of Detailed explanation of Nodejs memory management steps. For more information, please follow other related articles on the PHP Chinese website!

Statement:
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