Node 内存分配与垃圾回收
# Node 内存分配与垃圾回收
# Node 内存分配
Node中通过JavaScript只能使用部分内存(64位约1.4G,32位约0.7G)。V8对内存做了限制。因此这种限制下,将会导致Node无法直接操作大内存对象。 限制原因
- 首先V8是为浏览器而设计的;前期足以满足网页端的需求;
- 深层原因是V8的垃圾回收机制,垃圾回收耗时,引起JavaScript线程暂停执行时间 回收一次需要去50ms 以上 做一次增量的垃圾回收甚至要1s ,时间太长会影响性能和响应能力
- 可以手工调整内存大小
node --max-old-space-size=1700 test.js //单位为MB。设置老生代
node --max-new-space-size=1024 test.js //单位为KB。设置新生代
2
3
# V8的垃圾回收机制
主要的垃圾回收策略是基于分代式
的垃圾回收机制:将对象的存活时间进行不同的分代
;
V8的内存分代 在v8 中 主要讲内存分为新生代和老生代两代 ,新生代的对象存活时间较短,老生代中的对象存活时间较长或者为常驻内存的对象
V8整体内存大小就是新生代加上老生代 上面的方式可以分别设置 各自的内存大小 Scavenge算法 在分代的基础上新生代的对象主要是 通过 Scavenge 算法进行垃圾回收 在 Scavenge 的具体实现中 ,主要用到了 cheney 算法 ,这是一种采用复制方式的垃圾回收算法 主要的思想是将 新生代的堆空间一分为二,每一个部分称为semispace(半空间),其中一个处于使用称为From空间,一个处于闲置状态称为To空间,当我们分配的对象先在From 空间中进行分配, 当开始进行垃圾回收的时候,会检查From 空间中的存活对象,这些存货对象将被复制到To 空间中, 而非存活的对象占用的空间就会被释放,完成复制以后 ,彼此的角色会发生变化,From 变成 To , To 变成From 简而言之 就是通过两个半空间的交换复制,清除一分部分已经死亡的对象。 优点就是空间效率上比较高,缺点就是只能使用新生代空间的一半 牺牲空间换时间的做法。 当一个对象经过多次复制以后还是存活的状态,则认为是一个生命周期较长的对象,随后被移动到老生代的空间进行管理
在新生代的两个半空间进行角色转换或者反转的时候 ,在一定的条件之下需要将存活时间比较长的对象移动到老生代空间中 完成对象的晋升操作
首先晋升的条件是:
1、是否经理过 Scavenge 回收 默认情况下 对象从From 空间复制到To 空间时 会检查内存地址来判断是否已经经理过一个 scavenge 回收 ,如果经历过 则会移送带老生代空间中进行管理 ,如果没有则会复制到To 空间
2、To 空间的内存占用比超过限制 另外就是To空间的占用比列 如果To 空间的使用超过 25% 则这个对象直接升级到老生代中 (25% 是由于To空间会变成From空间,如果占用比列过高,会影响后续的内存分配 )
Mark-Sweep & Mark-Compact (标记清除) 老生代空间的对象由于存活的对象占比比较多,所以没有采用新生代的算法来回收,而是采用了 Mark-Sweep & Mark-Compact 组合方式 Mark-Sweep 是标记清除的意思 分为两个阶段 标记和清除 ,在其标记阶段遍历堆中的所有对象,并标记活着的对象,在随后的清除阶段中,只清除未标记的对象,Mark-sweep只清理死亡对象, 但是 Mark-Sweep在一次清理之后,内存空间会出现不连续的状态,这种内存碎片会对后续的内存分配造成一定的问题,当出现分配一个很大对象的时候,所有的内存碎片都无法完成此次分配 就会提前触发垃圾回收的 ,影响程序的性能。 黑色的标记为死亡的对象
为了解决 mark-sweep 的内存碎片问题 mark-compact 标记整理 载气标记清除的基础上演变而来的,差别就是对象在标记死亡以后 整理的过程中 将活着的对象往一段移动 白色为存活的对象 深色的为死亡的对象 浅色的为存活的对象移动后占用的内存空间
Incremental Marking (增量标记)
在V8进行垃圾回收的时候 为了避免应用逻辑的与垃圾回收器看到的不一致状况,垃圾回收器的三种算法 都会讲应用的逻辑暂停下来 等待执行完垃圾回收之后再执行,这种行为称为 " 全停顿 " ,
在V8 的分代式垃圾回收中 一次小垃圾回收的只会影响新生代,且由于新生代默认配置小,且存活对象较少 全停顿影响不大, 但是老生代的配置较大,并且存活对象较多 ,全停顿 的回收标记造成的停顿会影响程序的响应时间 需要设法改善,为了降低全堆垃圾回收带来的停顿时间, V8 采用了增量标记 ,也就拆分小步进行,每做完一步,执行一会JavaScript应用逻辑,
参考书籍:
[1]朴灵.深入浅出Node.js[M].人民邮电出版社:北京,2013-12-1:0.