图解 Google V8
李兵
前盛大创新院高级研究员
立即订阅
3369 人已学习
课程目录
已完结 24 讲
0/4登录后,你可以任选4讲全文学习。
宏观视角 (2讲)
开篇词 | 如何学习谷歌高性能 JavaScript 引擎V8?
免费
01 | V8是如何执行一段JavaScript代码的?
JavaScript设计思想篇 (7讲)
02 | 函数即对象:一篇文章彻底搞懂JavaScript的函数特点
03 | 快属性和慢属性:V8是怎样提升对象属性访问速度的?
04 | 函数表达式:涉及大量概念,函数表达式到底该怎么学?
05|原型链:V8是如何实现对象继承的?
06|作用域链:V8是如何查找变量的?
07|类型转换:V8是怎么实现1+“2”的?
08|答疑:如何构建和使用V8的调试工具d8?
V8编译流水线 (8讲)
09 | 运行时环境:运行JavaScript代码的基石
10 | 机器代码:二进制机器码究竟是如何被CPU执行的?
11 | 堆和栈:函数调用是如何影响到内存布局的?
12 | 延迟解析:V8是如何实现闭包的?
13 | 字节码(一):V8为什么又重新引入字节码?
14|字节码(二):解释器是如何解释执行字节码的?
15 | 隐藏类:如何在内存中快速查找对象属性?
16 | 答疑: V8是怎么通过内联缓存来提升函数执行效率的?
事件循环和垃圾回收 (6讲)
17 | 消息队列:V8是怎么实现回调函数的?
18 | 异步编程(一):V8是如何实现微任务的?
19|异步编程(二):V8是如何实现async/await的?
20 | 垃圾回收(一):V8的两个垃圾回收器是如何工作的?
21 | 垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
22|答疑:几种常见内存问题的解决策略
结束语 (1讲)
结束语 | 我的前端学习踩坑史
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

20 | 垃圾回收(一):V8的两个垃圾回收器是如何工作的?

李兵 2020-04-30
你好,我是李兵。
我们都知道,JavaScript 是一门自动垃圾回收的语言,也就是说,我们不需要去手动回收垃圾数据,这一切都交给 V8 的垃圾回收器来完成。V8 为了更高效地回收垃圾,引入了两个垃圾回收器,它们分别针对着不同的场景。
那这两个回收器究竟是如何工作的呢,这节课我们就来分析这个问题。

垃圾数据是怎么产生的?

首先,我们看看垃圾数据是怎么产生的。
无论是使用什么语言,我们都会频繁地使用数据,这些数据会被存放到栈和堆中,通常的方式是在内存中创建一块空间,使用这块空间,在不需要的时候回收这块空间。
比如下面这样一句代码:
window.test = new Object()
window.test.a = new Uint16Array(100)
当 JavaScript 执行这段代码的时候,会先为 window 对象添加一个 test 属性,并在堆中创建了一个空对象,并将该对象的地址指向了 window.test 属性。随后又创建一个大小为 100 的数组,并将属性地址指向了 test.a 的属性值。此时的内存布局图如下所示:
我们可以看到,栈中保存了指向 window 对象的指针,通过栈中 window 的地址,我们可以到达 window 对象,通过 window 对象可以到达 test 对象,通过 test 对象还可以到达 a 对象。
如果此时,我将另外一个对象赋给了 a 属性,代码如下所示:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《图解 Google V8》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(16)

  • 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-30
    3
    5
  • 大力
    麻烦老师能不能讲讲 Scavenge 与 Mark-Compact 算法的不同点?
    2020-05-02
    2
  • 一步
    上面那段代码最大的问题就是 strToArray 函数中的 let arr = new Uint16Array(str.length),
    在 foo 函数每次循环执行都会在堆中生成新的数组,这里可以在 foo 函数声明一个数组,然后每次调用 strToArray 函数的时候传递 进去就可以了

    作者回复: 是的

    2020-04-30
    2
  • 刘长锋
    老师好:

    “其实这两个特点不仅仅适用于 JavaScript,同样适用于大多数的动态语言,如 Java、Python 等。”

    这句话,是不是应该写成适合于大多数编程语言?

    为什么适合于动态语言呢?

    java 是典型的静态语言吧?

    作者回复: 嗯,我修改下

    2020-05-10
    1
  • 子云
    老师我有两个疑惑,我看到其他的文章中说新生代是 64位操作系统有32MB,32位系统有16MB,而您的文章中说的是8MB,那么是怎么回事呢。。
    还有其他的文章中说的新生代提升到老生带是
    * 已经经历过1次 Scavenge 回收。
    * To(闲置)空间的内存占用超过25%。
    似乎也和您的说法不一样呀
    2020-06-08
  • 子云
    我在看node buffer模块的时候,得知buffer存的东西在堆外内存上,这里的uintarray难道不是吗?它还是分配在堆里的?
    2020-06-08
  • 断线人偶
    主垃圾回收器的两种算法是同时使用还是有个策略?还是说早期用的是标记 - 清除算法,现在都是使用标记 - 整理算法?

    作者回复: 同时使用的,并不是所有时候都需要做内存整理

    2020-05-24
  • 路易
    请教老师:引用计数的垃圾回收机制,目前只看到iOS中使用,想知道苹果为啥选择引用计数,而其他很多语言都采用GC呢?因为GC有stop-the-world的问题,而引用计数方法貌似主要是会有循环引用问题,但是循环引用问题写代码时注意就不会有问题了,而stop-the-world是无法避免的。所以我个人更倾向于引用计数的方案,不知道老师怎么认为的呢?

    作者回复: 引用计数存在无法回收循环引用的问题,以前ie的js引擎就采用了循环引用的方式,现在都切换回来了

    2020-05-12
  • 草原上的骆驼🐫
    strToArray函数中的变量i,len, arr在foo函数每次循环后,都会变成垃圾数据,其中i和len会通过副垃圾回收器的Scavenge算法进行回收。arr会通过主垃圾回收器的标记回收方式回收

    作者回复: i len 本质是分配在栈上的,当前作用域执行结束就会回收掉,而arr是分配在堆中的,当前块退出后,这块数据就没用了,也没有引用了,所以这块数据就会变成垃圾数据

    2020-05-10
    1
  • yunplane
    栈里的数据不需要清除吗?怎么清除?

    作者回复: 滑动下栈指针就清除了,速度非常快

    2020-05-06
    1
  • ヾ(◍°∇°◍)ノ゙
    不好意思 问个node的问题。今天被一个nodejs问题搞晕了,引入一个模块,这个模块a里有一个 属性 c: C3 其中C3是个class, 我想判断C3是不是C1 继承来的,用的是 a.c.prototype instanceof C1 , 这时有报错 C1 不存在, 但是当我import 进来 import C1 from “C1” 这样进来可以执行,但是 a.c.prototype instanceof C1 这个会一直是false。搞了很久就一直没搞出结果,最后打印出来两个Function都一摸一样了,还是用等号判断是false。最后我不得不使用了__proto__遍历判断这种硬来的方式先绕过了。不知道是不是nodejs的module和export引起的,我在chrome上用class测试是OK的
    2020-04-30
    3
  • Miracle
    有一个疑问:新生代在进行垃圾回收的时候,复制整理后的空闲区域和对象区域进行反转的时候,对象区域是整体清空吗,还是只清除标记的垃圾数据

    作者回复: 全部清空

    2020-04-30
    1
  • HoSalt
    windows指向的对象放在堆上面,那如何做到全局对象的属性和全局变量统一呢(var声明的变量)?
    2020-04-30
  • luckyone
    函数里new array 会导致新生代不停触发gc,导致影响性能,改进方案可以吧array 提取出函数调用的环境这样可以放到老生代不会平凡gc

    作者回复: 没问题

    2020-04-30
  • Z_CHP
    有个疑惑,没有被GC Root遍历触达的对象就是垃圾数据。那在垃圾清理的过程中,没有被遍历到的对象是如何被标记为垃圾数据的呢?

    作者回复: 比如在标记之前,将所有对象设置为白色,然后遍历到的设置为黑色,最终白色的都视为垃圾数据

    2020-04-30
    2
  • 咪呐!哦哈哟嘶!٩(ˊᗜˋ*)...
    循环引用的怎么做垃圾回收?

    作者回复: 采用引用计数的垃圾回收器不好解决循环引用的问题,但是目前v8的标记清理方式可以解决循环引用的问题

    2020-04-30
    3
收起评论
16
返回
顶部