V8
的垃圾回收机制基于
分代回收机制,这个机制又基于
世代假说,这个假说有两个特点,一个是
新生的对象容易早死,另一个是
不死的对象会活得更久。基于这个假说,
V8
引擎将内存分为了
新生代和
老生代。
新创建的对象或者只经历一次的垃圾回收的对象被称为新生代。
新生代被分为 From
和 To
两个空间。这两个空间是绝对分隔的。
经历过多次垃圾回收的对象被称为老生代。
老生代也被分为两个空间,一个叫 Old pointer space
,另一个叫 Old data space
。这两个空间是连接的。
和操作系统的位数有关,当操作系统是64
位的时候,V8
引擎的内存空间是 1.4G(1464MB)
,当操作系统是32
位的时候,V8
引擎的内存空间是 0.7G(732MB)
。
64
位操作系统的新生代的空间为 64MB
,老生代的空间为 1400MB
。
32
位操作系统的新生代的空间为 32MB
,老生代的空间为 700MB
。
新生代被分为 From
和 To
两个空间,To
一般是闲置的。当 From
空间满了的时候就会执行 Scavenge
算法进行垃圾回收。
当我们执行垃圾回收算法的时候应用逻辑将会停止,等垃圾回收结束后再继续执行。Scavenge
这个算法分为三步:
From
空间的存活对象,如果对象存活则判断对象是否满足晋升到老生代的条件,如果满足条件则晋升到老生代。如果不满足条件则移动到 To
空间。From
空间和 To
空间角色进行交换。新生代对象晋升到老生代有两个条件:
Scavenge
回收。若经历过,则将对象从 From
空间复制到老生代中;若没有经历,则复制到 To
空间。To
空间的内存使用占比是否超过限制。当对象从 From
空间复制到 To
空间时,若 To
空间使用超过 25%
,则对象直接晋升到老生代中。设置 25%
的原因主要是因为算法结束后,两个空间结束后会交换位置,如果 To
空间的内存太小,会影响后续的内存分配。老生代采用了标记清除法和标记压缩法。
标记清除法首先会对内存中存活的对象进行标记,标记结束后清除掉那些没有标记的对象。由于标记清除后会造成很多的内存碎片,不便于后面的内存分配。所以为了解决内存碎片的问题引入了标记压缩法。
由于在进行垃圾回收的时候会暂停应用的逻辑,对于新生代方法由于内存小,每次停顿的时间不会太长,但对于老生代来说每次垃圾回收的时间长,停顿会造成很大的影响。为了解决这个问题 V8
引入了增量标记的方法,将一次停顿进行的过程分为了多步,每次执行完一小步就让运行逻辑执行一会,就这样交替运行。