password
Created
Feb 16, 2023 11:01 AM
type
Post
status
Published
date
Jul 17, 2021
slug
summary
Chrome(本质上是V8)的垃圾回收被设计成了两个区块
• 新生代区: 负责大部分临时对象的处理
• 老生代区: 对于数次新生代中没有清除掉的对象, 会被转入这个区, 老生代区中的对象的GC频率会降低
tags
Chrome
垃圾回收
category
原理
icon
chrome中其实大多数对象的生存周期都很短. 基本经过一次GC之后, 就会被释放掉.
而只有少部分的对象, 其生存周期很长, 相应的, 我们不需要对齐进行多次检测和判断
因此Chrome(本质上是V8)的垃圾回收被设计成了两个区块
- 新生代区: 负责大部分临时对象的处理
- 老生代区: 对于数次新生代中没有清除掉的对象, 会被转入这个区, 老生代区中的对象的GC频率会降低
新生代区
因为其GC频次高, 因此占用的内存则很少, 以便快速进行遍历和清除工作
新生代中使用了Scavenge算法来进行无用临时对象的清除工作
- Scavenge算法是一个典型的空间换时间的复制算法, 在空间占用不大的场景下非常实用.
Scavenge算法将新生代分为两个区块(from-space to-space), 在GC工作过程中, 会将from-space中的活动对象, 复制到to-space中. 此时from-space清空, 变成to-space. 对应的to-space会变成from-space. 重复此流程.
如何区分活动对象和非活动对象?
从根集遍历, 如果这个对象被搜索到引用, 则代表未活动对象, 否则则为非活动对象
在什么时机会将新生代放到老生代?
新生代中具体又区分了两个区: nursery区和intermediate区. 在活动对象复制的过程中, 会将其复制到to-space的intermediate区. 当下次复制时, 如果发现复制的对象在intermediate区. 则将其放到老生代区.
老生代区
在老生代空间中采用了 Mark-Sweep(标记清除) 和 Mark-Compact(标记整理) 算法
- Mark-Sweep 标记清除
与新生代所不同的是, 老生代中主要是活动对象, 因此需要标记活动对象, 并将其操作清除掉.
标记清除主要分为两个阶段:
- 标记阶段: 将老生代进行第一次扫描, 标记活动对象
- 清理阶段; 清除未被标记的对象
被清除的对象遗留下了小片小片的内存空间, 为了保证内存空间的有效利用, 因此还需要进行内存空间的整理, 也就是标记整理
- Mark-Compact 标记整理
将所有的活动对象整理成无空余内存空间碎片的内存区, 以有效利用内存占用.
全停顿
因为期间需要进行活动对象的移动处理, 在这期间是无法进行任何的JS逻辑操作的, 这个过程被称为全停顿.
如果老生代对象多且大, 那么全停顿的时间就会变长, 页面就会显得卡顿.
Orinoco优化
核心目的是为了降低全停顿导致卡顿的问题
主要使用: 增量标记, 惰性清理, 并发, 来降低全停顿的影响
增量标记
将全量标记拆分成一个个任务, 穿插在js逻辑之间执行. 类似于react的fiber的机制
惰性清理
当当前可用内存足够时, 可以将清理延后一些, 让js逻辑先执行
并发
辅助线程执行GC的标记等流程, 仅最后操作对象时占用主线程
并行
辅助线程和主线程同时进行不干扰的GC活动, 以降低主线程时间
参考: 深入理解Chrome V8垃圾回收机制Updated Aug 25, 2023
深入理解Chrome V8垃圾回收机制
Updated Aug 25, 2023