谷歌浏览器v8引擎垃圾回收机制
- 内存:栈内存与堆内存和其他内存
- 垃圾回收是指堆内存中的垃圾回收
新生代与老生代 new space & old space
- 堆内存中存在新生代与老生代内存
- 32位操作系统:新生代内存32M,老生代内存700M
- 64位操作系统: 新生代内存64M,老生代内存1400M
为什么只设定到1.4G呢?
- js是单线程的,垃圾回收时,线程会等待垃圾回收完毕再执行,内存越大意味着垃圾越多,GC时间越长,等待时间也越长
- js设计时,没有考虑那多,比如后来的node.js
新生代内存 Young generation
新生代内存又分为from-space 和 to-space 两个区域,大小1:1,32M时就是各位16M;
新生代中的垃圾回收 Scavenger
增加新变量时,先存入from-space中,当from-space存满,会进行垃圾回收, 没有用的变量直接清理掉,剩余有用的变量复制存入到to-space,直到本轮垃圾回收完,再将to-space中变量复制到from-space中,如此循环往复。 当to-space的内存占用大于25%时,新生代内存就会变为老生代内存。
- 优点:时间复杂度低,因为过程中变量是直接复制的
- 缺点:浪费了新生代内存的一半内存,因为to-space是闲置的
这种回收机制显然不能用于老生代内存的垃圾回收,试想一下,1400M的老生代空一半,那就是700M的内存浪费了
老生代垃圾回收机制 Old generation
标记清除 --广度扫描,全停顿标记
从根变量(类似window这个概念)开始,广度扫描,标记互相引用的标量,打上标记,没有标记的变量视为垃圾清除
- 缺点:
- 全停顿等待GC时间长
- 内存被分割
标记整理
从根变量开始,广度扫描,标记互相引用的变量,先整理,将标记的标量按照顺序先覆盖未标记的标量,整理好后,其余未覆盖的变量删除
- 优点: - 内存整理,未被分割 - 覆盖部分无用变量,删除的动作减少,速度更快
- 缺点: - 全停顿等待时间较长,但相比标记清除更为优化
增量标记&三色标记法
V8 增量标记(Incremental Marking)和三色标记法(Tri-color Marking)是 JavaScript 垃圾收集(Garbage Collection)中的两种常用技术,用于管理内存中的对象。
-
V8 增量标记是 V8 引擎(Google 开发的 JavaScript 引擎)中采用的一种垃圾收集算法。它通过将标记过程划分为一系列较小的任务来实现,以便在应用程序执行期间逐步完成标记工作,而不会阻塞主线程。这样可以降低垃圾收集对应用程序性能的影响。
-
三色标记法是一种广泛应用于垃圾收集领域的算法,它将对象分为三种颜色:白色、灰色和黑色。白色对象表示尚未被垃圾收集器检查的对象,灰色对象表示已经被标记但需要进一步检查其引用的对象,黑色对象表示已经被标记且其引用也被检查过的对象。三色标记法通过逐步将白色对象转换为灰色对象和黑色对象,最终完成垃圾收集过程。
-
在 V8 引擎中,增量标记和三色标记法结合使用,以实现高效的垃圾收集。增量标记通过将标记过程划分为一系列较小的任务来避免在主线程上产生长时间的停顿,而三色标记法则用于高效地遍历和标记对象图。这种组合有助于提高应用程序的性能和响应速度。
增量式垃圾回收是主线程间歇性的去做少量的垃圾回收的方式
- 好处:等待时间短,利于用户体验,相当于将垃圾回收分割为N次
三色标记法
白色:未被标记;
灰色:已标记,还未遍历完成;
黑色:已标记,且遍历完成;
- 1.初始白色,根变量开始,根变量引用的置为灰色,
- 2.灰色继续向下遍历,将其引用的变量置为灰色,自身置为黑色
- 3.继续向下,直至变量没有其他引用,变为黑白两色
- 4.删除白色无标记变量
优化
- max-old-space-size=‘大小’来扩大老生代内存空间
- 尽量使用局部作用域变量,少使用全局变量,因为局部变量会随着函数执行结束被清楚
- 使用weakMap与weakSet弱引用