Skip to content

v8 下的垃圾回收机制 #42

Open
@myLightLin

Description

@myLightLin

JS 是一门动态弱类型的高级语言,高级语言的特点就是垃圾回收通常不用程序员自己做,而是由语言引擎去优化实现。本文简单介绍下 Chrome 浏览器 v8 引擎下的垃圾回收机制。

垃圾回收相关概念

JS 代码所在的内存空间分为栈和堆,栈中存放的是基本数据类型,堆中存放的是引用类型。栈就是我们常见到的调用栈,也就是执行上下文,执行上下文栈里会通过一个 ESP 指针来指向当前正在执行的上下文,那么当指针从一个上下文移动到另一个时,上一个执行上下文就销毁回收了,对应的局部活动对象也随之销毁;而对于堆来说,因为存放的是引用类型的数据,这些数据在内存里分配了地址,像这类数据就需要垃圾回收器来做。

理解垃圾回收前,先要了解下垃圾回收领域的一个理论,叫做「代际假说」,它的主要特点是:

  • 大部分对象在内存中存在时间很短,很多对象一经分配,很快就变得不可访问
  • 不死的对象,会活得更久

根据这个理论,v8 将堆分为新生代和老生代两个区域。新生代中存放的是存活时间比较短的对象,其大小大概是 1 ~ 8 M,而老生代中存放的则是存活时间比较长的对象,它的容量可以很大。相对应的,有两个垃圾回收器:主垃圾回收器副垃圾回收器。主垃圾回收器主要负责老生代的垃圾回收,而副垃圾回收器则负责新生代的垃圾回收。

这两个垃圾回收器在回收时,执行流程大致是共通的:

  • 标记空间里的活动对象和非活动对象
  • 回收非活动对象所占据的内存
  • 进行内存整理

副垃圾回收器

副垃圾回收器主要针对新生代区域,在回收时采用 Scavenge 算法,它将空间对半划分为对象区域和空闲区域,新加入的对象首先分配到对象区域里。而当对象区域满时,就需要进行垃圾清理工作,具体过程如下:

  • 首先对对象区域中的垃圾做标记,标记完后进行清理,然后将清理后存活的对象复制到空闲区域中,在这个过程中会有序地排列对象,相当于完成了内存整理的动作,复制完成后,内存碎片也被整理掉了。
  • 接着角色翻转,交换对象区域和空闲区域,垃圾回收完成。

新生代垃圾回收的特点是每次都要将存活对象从对象区域复制到空闲区域,这个复制操作需要时间成本,所以为了执行效率,新生代空间不宜设置过大。同时为了解决新生代空间容易装满的问题,v8 采取对象晋升策略,如果一个对象如果经过两次垃圾回收后依然存活,就会从新生代转移到老生代里。

主垃圾回收器

主要针对老生代区域,采用标记-清除算法。从根元素开始遍历,可达的称为活动对象,不可达的判定为垃圾数据。由于老生代中存放的对象是比较大且存活时间久,而清理的过程是标记一部分,清理另一部分,那这个过程就会产生内存碎片。而如果内存碎片过多的话,会导致大的对象无法分配到足够的连续内存。于是 v8 团队又使用了一种新算法:标记-整理法。它前面的步骤跟标记-清除法是一样的,不一样的是对垃圾数据不直接清除,而是让存活的对象向一端移动,然后清理掉端边界里的垃圾数据。

全停顿

由于 JS 是运行在主线程之上的,一旦执行垃圾回收算法,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行,这种行为叫做全停顿(Stop-The-World)。对新生代来说还好,但老生代影响比较大,因为回收需要的时间更长,如果导致主线程暂停等待垃圾回收完毕,肯定会影响应用程序比如卡顿,所以 V8 将标记过程分为一个个的子标记过程,同时让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成,这个算法被称做「增量标记」(Incremental Marking)算法,它就是把一个完整的垃圾回收任务拆分为多个小任务,这些小的任务执行时间比较短,可以穿插在其他的 JS 任务里执行,所以能做到垃圾回收的同时也不会影响 JS 主线程代码的执行。

小结

  • 对于垃圾回收,先了解「代际假说」的理论
  • v8 引擎把内存分为新生代和老生代区域,新生代存放存活时间短的对象,老生代存放存活时间久的对象
  • 新生代区域空间比较小,大概 1-8 M,而老生代容量可以很大
  • 一个对象经过两次垃圾回收依然存活,则会从新生代转移到老生代去
  • 垃圾回收算法有:Scavenge 算法标记-清除法标记-整理法

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions