增量标记将单次几百毫秒的主线程停顿拆为多次几毫秒微暂停,穿插于JS执行间隙,缓解动画、输入等交互卡顿;它依赖三色标记与写屏障保障正确性,并协同并发标记、惰性清理及分代回收工作。

为什么传统标记会卡住主线程?
老式标记-清除算法需要一次性遍历整个堆的对象图(尤其老生代可能达几百 MB),期间 JS 完全停止(Stop-The-World)。用户会明显感知页面冻结,比如点击无反应、动画掉帧。
增量标记怎么拆分任务?
- 把标记过程分解为多个小单元,每次只处理一部分对象(例如几百个对象或限定耗时 5ms)
- 每执行一小段,就交还控制权给 JS 主线程,让它继续运行脚本、响应事件、渲染帧
- 下一次 JS 执行间隙(如空闲时间、事件循环微任务之后),再继续下一小段标记
- 配合写屏障(Write Barrier)实时捕获对象引用变更,避免漏标
三色标记法保障增量过程正确性
V8 用颜色区分对象状态:
- 白色:未访问,可能是垃圾
- 灰色:已访问,但子对象还没全部扫描完
- 黑色:已完全扫描,确认是活动对象
初始全白;标记启动后,根对象入灰,逐个出灰、染黑、将其子对象入灰;增量过程中只要保证灰色对象不被提前变黑,就能维持一致性。写屏障会在对象引用被修改时,把被修改的父对象重新推回灰色队列。
它不是孤立工作的,而是和其它机制协同
- 与并发标记配合:部分标记工作可交给辅助线程并行执行(不阻塞主线程)
- 与惰性清理配合:清除阶段也不一次性扫完,而是按需清理空闲内存页
- 嵌入在分代回收框架里:主要作用于老生代,新生代仍用快速 Scavenge 算法

















