快速学习nodejs系列:11、nodejs垃圾回收

nodejs的垃圾回收机制是由v8引擎自动管理的。php

nodejs的内存限制
在通常的后端语言(php)来讲,内存的使用上是没有限制的,但对于nodejs来讲只能使用系统的部分----64位系统为1.4G,32位系统位0.7G。这时若是你要处理个3G文件进行数据分析,即便系统的内存为8G,在该nodejs进程内存仍是会溢出。node

形成上面这个问题主要是由于nodejs是基于v8的,nodejs是经过v8本身的方式来管理内存的。那v8为何要限制堆内存的大小呢?缘由有2:
1.表层缘由:v8是为浏览器设计的,不大可能遇到大内存的情景。
2.深层缘由:v8垃圾回收机制的限制。以1.5G的堆内存为例,v8作一次小的垃圾回收须要50ms,作一次非增量的垃圾回收要1s。垃圾回收时会引发js的线程的暂停,在这样的时间花销下,应用的性能、响应能力会直线降低。
内存限制是能够打开的:
--max-old-space-size(老生代)
--max-new-space-size(新生代)
v8堆内存大小 = 老生代 + 新生代web

v8垃圾回收机制
v8垃圾回收主要是基于分代式垃圾回收机制。按对象的存活时间将内存的垃圾回收进行不一样的分代,分别对不一样的分代内存进行不一样的算法。算法

新生代--->存活时间较短的对象
老生代--->存活时间较长或常驻内存的对象
上面也说过,nodejs堆内存的大小是新生代内存空间加上老生代内存空间。后端

新生代算法
新生代主要是经过scavenge算法进行垃圾回收。数组

这是一种采用复制的方式来实现垃圾回收,将堆内存一分为二,每一个空间称为semispace。在这2个semispace空间中,只有一个处于使用中(称为from空间),另外一个处于空闲中(称为to空间)。开始分配时首先从from空间开始,当开始垃圾回收时,也是从from空间开始检查存活对象,把存活对象复制到to空间,而非存活对象占用的空间就会被释放。完成复制后,from空间和to空间角色对调。
从上面的过程能够知道,scavenge的缺点就是只使用了一半的堆内存,牺牲空间获取时间。浏览器

老生代经过mark-sweep、mark-comopact算法。session

mark-sweep标记清除,分为标记、清除2个阶段。mark-sweep先在标记阶段遍历堆内存中的全部对象,并标记存活的对象;在清除阶段把没有被标记的对象清除。能够看出,scavenge只复制存活的对象,mark-sweep只清理死亡的对象。由于在新生代中存活的对象占用小部分,而在老生代中死亡对象占用小部分,这是这2中算法高效的缘由。性能

Mark-compact标记整理,mark-sweep中会出现一个问题,在回收后,对内存会出现不连续的状态(内存碎片)。内存碎片会对后续的内存分配形成影响,由于会有这样一种状况:须要分配个大内存,而全部内存碎片都没法完成分配,这会提早触发垃圾回收,而这个回收时没必要要的。Mark-compact是在Mark-sweep基础上演变而来的,它主要区别在于:对象被标记后,在整理的过程当中会将存活的对象都往一端移动,移动完成后直接清除。spa

小结:在正常的使用过程当中,v8的内存限制仍是够用的,但nodejs的垃圾回收、单线程仍是会影响性能。想要高性能,须要让垃圾回收尽可能小。在实际的开发中要老生代对象的使用,如实现web服务的会话(session),通常会经过内存来存储(数组),在访问量大的状况下会致使老生代对象剧增,有可能形成溢出。若是要处理大内存的数据,好比读取3G的文件,咱们会经过可读流的pipe()方法,这样就不会受到v8内存的限制影响,提升了nodejs程序的健壮性。

相关文章
相关标签/搜索