V8垃圾回收系统梳理

内存中两种变量的存储

在V8中,JavaScript的内存空间分为栈(Stack)和堆(Heap)两部分。栈用于存储原始类型,如Number,String,Boolean,Null,Undefined,Symbol以及引用对象的内存地址,而堆用于存储引用类型的对象。

垃圾回收的基本思路是:查找内存中的所有变量,看哪些已经不再需要,然后释放这些变量所占用的内存。

所以V8中的垃圾回收可以分为栈回收堆回收

栈回收

在V8引擎中,函数调用的参数、返回地址和局部变量都存储在调用栈中。每当一个函数被调用时,都会创建一个新的栈帧,其中包含这些信息。而栈帧的回收则非常直接:一旦函数调用结束,其栈帧就会被立即移除。这种机制依赖于ESP(Extended Stack Pointer)指针,该指针始终指向栈的顶部,用于追踪哪些栈帧是活动的,哪些可以被安全回收。------参考文章

简单理解:说白了就是某个作用域代码执行完毕后,自动回收作用域内所有的普通数据类型的垃圾。

堆回收

堆中变量存储的分类

V8引擎引入所谓的"代际假说",即"大部分对象在内存中存在的时间很短",所以把堆内存分为新生代老生代两部分,新生代即对象一开始创建时存放的区域,一旦对象满足了一定的条件(也就是V8认为其会长时间存在于内存),那么它就会被移动("晋升")至老生代。

所以针对堆内存中的垃圾回收,也分为两种算法来分别处理新老生代。

新生代垃圾回收

采用Scavenge算法,简单来说就是Copy,也叫新生代互换。

结合上图:新生代空间等分成From空间与To空间,新声明的变量存放到新生代的From空间,直到From空间满了,这时候需要进行GC的垃圾回收。GC会根据代码分析出哪些obj不是垃圾,然后把非垃圾的obj对象直接copy到To空间,最后把From空间中的垃圾进行删除即可,至此存放对象的To空间变成From空间,原本的From空间变成To空间,从而开启新一轮的对象存储。

之所以新生代采用这种回收算法,可以从时空复杂度进行分析,首先我们会发现新生代的空间在同一时刻只有一半被利用,把空间进行了折半,目的就是为了对象转移时直接进行copy操作(肯定耗时非常低),可以理解为空间换时间。

并且新生代的总空间相较于老生代比较小,所以折半空间不会损失太多的内存空间,可以接受。

老生代垃圾回收

标记清除

在V8引擎早期,采用的是Mark-Sweep算法(标记清除),如下图:

注:上面图示的GC根节点并不是指浏览器的window对象,但可以类比window对象,我们可以通过window.xxx.xxx.xx访问所有的变量,自然可以通过GC的根节点访问所有的内存对象,一旦GC断开了与某个对象的联系,那么这个对象就可以理解为垃圾。

标记清除算法的完整步骤:

  1. 从GC的根节点开始进行"广度扫描"(专属术语)并把非垃圾进行标记
  2. 清除未被标记的对象

标记整理

现阶段Mark-Compact算法(标记整理)已经成为主流,如下图:

标记整理算法步骤:

  1. 先进行广度扫描并标记非垃圾变量
  2. 整理非垃圾变量的位置,目的是获取更大的连续空间,如上图一到图二(整理的过程中会对一些垃圾进行覆盖,可以理解为先整理后清除的原因)
  3. 垃圾清除

也就是相较于标记清除算法多了一步:在垃圾清除之前进行内存空间的整理

标记算法优化

如上我们所描述的标记,都是"全停顿标记",也就是说js主线程切换至GC垃圾回收线程时,在GC线程中会把所有的应该标记的变量都进行标记,然后进行大规模的清除。

这种标记算法的劣势就是时间开销大,导致GC线程占用的时间长,阻塞js主线程的运行。所以后期标记算法也进行了优化,衍生出来增量标记与三色标记法,这里就不详细记录了(感兴趣可观看视频讲解),总之优化的核心思想就是部分标记,从而减少GC线程对js线程运行时间的抢占。

plus

当然更早期的IE浏览器还使用过引用计数的堆回收算法,存在着不能解决循环引用问题等痛点。这里不再赘述。

相关推荐
王哈哈^_^1 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic2 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿3 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具3 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161774 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test4 小时前
js下载excel示例demo
前端·javascript·excel
Yaml44 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事4 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶4 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json