【知识体系】V8工作原理(2)- 垃圾回收

84 阅读4分钟

知识体系

  • 定义垃圾数据
  • 垃圾回收策略
  • 垃圾回收机制
    • 栈垃圾回收
    • 堆垃圾回收
      • 代际假说(The Generational Hypothesis)
      • 分代收集
  • 堆垃圾回收工作流程
  • 主/副垃圾回收器 - 堆垃圾
  • 全停顿 - 堆垃圾

垃圾数据

有些数据被使用之后,可能就不再需要了,这些数据被称为【垃圾数据】。
垃圾数据或占用内存,需要回收进行内存释放

垃圾回收策略

  • 手动回收(C/C++)- 代码控制
  • 自动回收(JS/Java/Python)

垃圾回收机制

栈垃圾的回收

ESP - 记录当前执行状态的指针

上代码

function foo(){
    var a = 1
    var b = {name:" 极客邦 "}
    function showName(){
      var c = " 极客时间 "
      var d = {name:" 极客时间 "}
    }
    showName()
}
foo()

10.png

如果】执行到showName函数时,JS引擎会创建showName函数的执行上下文,并将其压入栈中。同时还有一个ESP指向这个执行上下文,表示JS引擎正在执行这个函数。

如果】showName执行完成,ESP会下移到foo函数的执行上下文,同时伴随着showName执行上下文的销毁。

堆垃圾的回收

当栈中的数据被回收后,此时堆垃圾中的对象数据仍然占用着空间

此时,就需要用到JS中的垃圾回收器

代际假说

V8实现垃圾回收的基础

  • 两个特点
    • 大部分对象一经分配内存,很快便不可访问
    • 不死对象

分代收集

  • 两个区域
    • 新生代
      • 生存时间短的对象
      • 容量:1M ~ 8M
      • 启用副垃圾回收器
    • 老生代
      • 生存时间长的对象
      • 容量大
      • 启用主垃圾回收器

垃圾回收工作流程 - 堆垃圾

  • 标记空间中的 活动/非活动 对象
  • 回收 非活动 对象占据的空间
  • 内存整理。整理内存碎片(不连续的内存空间)【副垃圾回收器不会产生内存碎片】

主/副垃圾回收器 - 堆垃圾

副垃圾回收器

  • 负责新生区的垃圾回收。
    • 大多数小的对象都会分配到新生区。区域不大,垃圾回收比较频繁
  • 使用Scavenge算法处理
    • 把新生区对半划分(空闲区域/对象区域)

13.png

1. 新加入的对象被分配到 [对象区域]
2. 对象区域被写满时 => 执行垃圾回收操作
    【首先】标记 [对象区域] 中的垃圾
    【然后】复制 存活的对象到 [空闲区域] (有序排列 => 相当于内存整理)
    【最后】[对象区域] 与 [空闲区域] 角色翻转。
    完成垃圾对象的回收
【无限重复使用】

【由于】复制操作需要时间成本 
【所以】新生区空间设置比较小
【但是】空间小容易填满
【所以】JS引擎采用 【对象晋升策略】 => 经过两次垃圾回收还存活的对象,会被移到老生区

主垃圾回收器

  • 负责老生区的垃圾回收

    • 存储大对象数据
    • 存储新生区晋升过来的数据
  • 使用 标记-清除算法(Mark-Sweep)处理

    • 标记过程
    遍历调用栈,跟堆中的地址进行对比.
    【栈中存在,堆中也存在】活动对象
    【栈中不存在,堆中存在】垃圾数据,进行标记
    
    • 清除过程 15.png

产生内存碎片

  • 使用标记-整理算法(Mark-Component)处理
    • 标记过程跟 标记-清除算法一样
    • 后续不直接回收垃圾数据,而是让所有存活对象移向一端,然后清理掉垃圾数据。

16.png

全停顿 - 堆垃圾

垃圾回收运行在主线程上。进行垃圾回收时,会暂停JS脚本的运行;垃圾回收结束后再恢复脚本的执行。这个行为叫全停顿(Stop-The-World)

17.png

提出问题

  • 主线程被垃圾回收占用太久,会影响JS脚本的运行,可能会造成页面卡顿。

V8提出改进方案

  • 增量标记(Incremental Marking)
    • 将标记过程分为一个个的子标记,同时跟JS脚本交替运行,直到标记过程完成。 18.png
外部参考:
[垃圾回收:垃圾数据如何自动回收 | 浏览器工作原理与实践 (poetries.top)]
(https://blog.poetries.top/browser-working-principle/guide/part3/lesson13.html)