20 | 垃圾回收(一):V8的两个垃圾回收器是如何工作的?
李兵
该思维导图由 AI 生成,仅供参考
你好,我是李兵。
我们都知道,JavaScript 是一门自动垃圾回收的语言,也就是说,我们不需要去手动回收垃圾数据,这一切都交给 V8 的垃圾回收器来完成。V8 为了更高效地回收垃圾,引入了两个垃圾回收器,它们分别针对着不同的场景。
那这两个回收器究竟是如何工作的呢,这节课我们就来分析这个问题。
垃圾数据是怎么产生的?
首先,我们看看垃圾数据是怎么产生的。
无论是使用什么语言,我们都会频繁地使用数据,这些数据会被存放到栈和堆中,通常的方式是在内存中创建一块空间,使用这块空间,在不需要的时候回收这块空间。
比如下面这样一句代码:
当 JavaScript 执行这段代码的时候,会先为 window 对象添加一个 test 属性,并在堆中创建了一个空对象,并将该对象的地址指向了 window.test 属性。随后又创建一个大小为 100 的数组,并将属性地址指向了 test.a 的属性值。此时的内存布局图如下所示:
我们可以看到,栈中保存了指向 window 对象的指针,通过栈中 window 的地址,我们可以到达 window 对象,通过 window 对象可以到达 test 对象,通过 test 对象还可以到达 a 对象。
如果此时,我将另外一个对象赋给了 a 属性,代码如下所示:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
V8引擎的垃圾回收器是JavaScript自动垃圾回收的关键。文章介绍了垃圾数据的产生和V8引擎采用的两个垃圾回收器:副垃圾回收器-Minor GC (Scavenger)和主垃圾回收器-Major GC。副垃圾回收器主要负责新生代的垃圾回收,采用Scavenge算法。而主垃圾回收器则负责老生代中的垃圾回收,采用标记-清除(Mark-Sweep)和标记-整理(Mark-Compact)算法。V8引擎的垃圾回收策略建立在代际假说的基础上,根据对象生存周期的不同采用不同的算法,以达到最佳效果。文章还提出了一个代码示例,并邀请读者思考V8执行该代码时产生的垃圾数据以及如何优化代码。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》,新⼈⾸单¥59
《图解 Google V8》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(28)
- 最新
- 精选
- sugar置顶分享一篇好几年前我刚开始研读v8源码时,参考的GC相关资料:https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/ 还有这个github仓库:https://github.com/yjhjstz/deep-into-node 如今与老师的这篇
作者回复: 赞
2020-04-30422 - 奕上面那段代码最大的问题就是 strToArray 函数中的 let arr = new Uint16Array(str.length), 在 foo 函数每次循环执行都会在堆中生成新的数组,这里可以在 foo 函数声明一个数组,然后每次调用 strToArray 函数的时候传递 进去就可以了
作者回复: 是的
2020-04-3012 - 阿郑有个疑惑,没有被GC Root遍历触达的对象就是垃圾数据。那在垃圾清理的过程中,没有被遍历到的对象是如何被标记为垃圾数据的呢?
作者回复: 比如在标记之前,将所有对象设置为白色,然后遍历到的设置为黑色,最终白色的都视为垃圾数据
2020-04-3038 - 断线人偶主垃圾回收器的两种算法是同时使用还是有个策略?还是说早期用的是标记 - 清除算法,现在都是使用标记 - 整理算法?
作者回复: 同时使用的,并不是所有时候都需要做内存整理
2020-05-243 - yunplane栈里的数据不需要清除吗?怎么清除?
作者回复: 滑动下栈指针就清除了,速度非常快
2020-05-0623 - luckyone函数里new array 会导致新生代不停触发gc,导致影响性能,改进方案可以吧array 提取出函数调用的环境这样可以放到老生代不会平凡gc
作者回复: 没问题
2020-04-303 - 刘长锋老师好: “其实这两个特点不仅仅适用于 JavaScript,同样适用于大多数的动态语言,如 Java、Python 等。” 这句话,是不是应该写成适合于大多数编程语言? 为什么适合于动态语言呢? java 是典型的静态语言吧?
作者回复: 嗯,我修改下
2020-05-1022 - Miracle有一个疑问:新生代在进行垃圾回收的时候,复制整理后的空闲区域和对象区域进行反转的时候,对象区域是整体清空吗,还是只清除标记的垃圾数据
作者回复: 全部清空
2020-04-3022 - 蹦哒请教老师:引用计数的垃圾回收机制,目前只看到iOS中使用,想知道苹果为啥选择引用计数,而其他很多语言都采用GC呢?因为GC有stop-the-world的问题,而引用计数方法貌似主要是会有循环引用问题,但是循环引用问题写代码时注意就不会有问题了,而stop-the-world是无法避免的。所以我个人更倾向于引用计数的方案,不知道老师怎么认为的呢?
作者回复: 引用计数存在无法回收循环引用的问题,以前ie的js引擎就采用了循环引用的方式,现在都切换回来了
2020-05-1221 - 草原上的骆驼🐫strToArray函数中的变量i,len, arr在foo函数每次循环后,都会变成垃圾数据,其中i和len会通过副垃圾回收器的Scavenge算法进行回收。arr会通过主垃圾回收器的标记回收方式回收
作者回复: i len 本质是分配在栈上的,当前作用域执行结束就会回收掉,而arr是分配在堆中的,当前块退出后,这块数据就没用了,也没有引用了,所以这块数据就会变成垃圾数据
2020-05-1021
收起评论