垃圾回收算法

v8的内存划分
  • v8大致分为,垃圾回收在堆里进行。node

  • 堆内存分多个模块:算法

    • New space浏览器

      大多数的对象开始都会被分配在这里,这个区域相对较小可是垃圾回收特别频繁,该区域被对半分为两半(分为Semi space From 和 Semi space To )ide

    • Old space优化

      新生代中的对象在存活一段时间后就会被转移到老生代内存区,相对于新生代该内存区域的垃圾回收频率较低。spa

    • Large object space操作系统

      存放体积超越其余区域大小的对象,每一个对象都会有本身的内存,垃圾回收不会移动大对象区。线程

    • Code spacecode

      代码对象会被分配在这里,惟一拥有执行权限的内存区域。对象

    • Cells pace

    • Property cell space

    • Map space

  • 垃圾回收发生在新生代(New space)和老生代(Old space)中。

新生代和老生代的内存大小

根据操做系统不一样:32位为0.7G,64位为1.4G

新生代 老生代
32位系统 34M 700M
64位系统 64M 1400M

最新版V14内存为2G

垃圾回收的算法

新生代使用的是Scavenge(新生代互换算法)

老生代如今使用的是Mark-Compact(标记整理算法),之前使用Mark-Sweep(标记清除算法),最古老的是引用计数算法

Scavenge

过程:

每次新加入的变量都会放入from,当from中内存占满时会开始执行垃圾回收:对from中不用的内存回收,还存在引用的内存会被复制到to中,当此次垃圾回收结束的时候会出现from中为空,to中留下还存在引用的内存,这时会将from和to交换,最后就是from中留下有引用的内存,to中保持为空。

由于From和To中各占一半,而且To始终不会存放,因此会浪费一半的空间。该算法是使用空间换取时间,而老生代比新生代大不少,因此用该算法不合理。


引用计数法

过程:

查看是否有其它的对象在引用该对象,若是没有则把它清除。

该方法没法处理对象间的循环引用,容易形成内存泄漏。

在 IE 时代就被抛弃了。


Mark-Sweep

该算法是早先使用的算法,如今已经不被使用

过程:

垃圾回收会在内部构件一个根节点(能够看做是浏览器中的window,node中的gelobal)。首先对老生代中的全部对象进行一次广度扫描,查找到有对根节点引用的对象时会把它标记,最后将没有标记的对象垃圾回收。

该算法没有进行内存的碎片整理,因此之后再须要非陪一个大的对象时会提早触发垃圾回收,为解决这个问题就产生了Mark-Compact(标记整理算法)


Mark-Compact

在标记清除法的基础上进行了优化:

  • 它在执行垃圾回收的开始把全部被标记内存移动到一块儿,而后清除未被标记的内存,这样就解决了大对象存入时连续空间不足的问题。

  • 原先的Mark-Sweep算法会在执行垃圾回收时进行一次广度扫描,将全部有引用节点标记,这叫作全停顿标记,由于JS是单线程的,因此一次垃圾回收的时间内所有标记对时间的花费会比较大;而如今则是使用增量标记法和三色标记法来进行标记。

增量标记法和三色标记法

将代码运行和垃圾回收之间的且换变得更加频繁,而且每次垃圾回收的时候只向下查找一层。

该算法把每一个节点分为三种状态:

  • 白色:没有被查找的
  • 灰色:下次从这里开始查找,引用该对象的对象没有被查找到
  • 黑色:被标记的,引用该对象的对象已经被查找过了

三色标记法

每次垃圾回收时都进行一次查找,直到引用树所有标黑后再进行排序-回收。

该模式将每次垃圾回收的标记拆分开插入代码的运行中,比原先的全停顿标记法体验更好。(在后续也引入了增量式整理和延迟清理,让停顿变得更短)


新生代晋升到老生代

这个判断很简单:

  • 首先判断该内存是否经历过一次垃圾回收,没经历过的会放入to中。
  • 而后判断这时to是否已经使用了25%(8M),若是没有也会放入to中。
  • 两个条件都判断为true时会被晋升到老生代中。
相关文章
相关标签/搜索