v8垃圾回收机制笔记(二)

230 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

1、新生代:即cppy。Scavenge算法(新生代互换)

2、老生代:即标记整理清除。Mark-Sweep(标记清除)、Mark-Compact(标记整理)

一、新生代

1、介绍

1)、有两个部分,from空间 和 to空间

2)、空间是一样大

2、算法过程

1)、一开始变量都是存在Semi space from空间,比如变量是obj,string,num 这3个。然后删掉变量string,num之后,代码是删掉了,但其在内存里依然存在,只是会被标记起来,如obj,string(垃圾),num(垃圾)。

2)、此时新加了一个新的变量arr,发现from空间已经满了,那么gc就会把from进行垃圾清除,然后把obj、arr复制到to空间,等from空间清完之后,便会把to空间里的变量对调到from空间。如此反复。所以这种方式叫做新生代互换。

3、问题

1)、新生代为什么要采用复制这种形式呢?

算法复杂度有两种维度,分别是空间复杂度和时间复杂度。而新生代就是采用牺牲空间换取时间的方式。因为变量from空间和to空间对换的时候,总会一方是空闲的,就是有一半的空间是被浪费的,而copy是程序里最简单的,所以新生代的方式是牺牲空间换取时间。

二、老生代

1、方式

1)、Mark-Sweep标记清除 过程

广度扫描 -- 标记 -- 当gc运行时就把没标记的变量清除掉

2)、Mark-Compact标记征集 过程

广度扫描 -- 标记 -- 整理(整理成一个连续的内存空间)--清除剩余没被标记的变量

2、问题

1)、compact 是采用先清除后整理 还是 先整理后清除呢?

后者。当整理移动变量的时候,是覆盖原有空间上的垃圾变量,所以下一步要清除的垃圾变量就会少一个。

2)、为什么要整理?

因为我们需要连续的内存空间。对象是存储在堆,堆是连续的线性的存储空间。当一个数组要存储的时候,它需要一串或一片连续的空间,若存储的空间不够,它就放不下。

后语

1、早期v8引擎的标记算法是全停顿标记(一次性把垃圾变量全标记上),现在用的是增量标记&三色标记法即黑白灰。 2、上面的介绍的标记方法是全停顿标记法。那什么是增量标记呢?js线程是单线程,先运行主线程 -- 垃圾回收 -- 主线程 -- 回收 这样的顺序,而现在线程切换频度会更快,标记的层数更少。当代码运行的时候gc开始垃圾回收了就回标记这一层垃圾变量,颜色为黑,代码继续运行,gc开始了就标记第二层为黑,第一层就变成灰,代码继续运行,gc开始了就标记第三层为黑,第二层就变成灰,第三层就变成白......