垃圾回收机制

垃圾回收机制

介绍

垃圾回收是指将无用的内存释放的机制。

在JS中基本类型是使用栈存储的,而引用类型的值是使用堆存储的,引用地址依然是使用栈存储。所以当我们将一个引用类型的值设置为null时,栈存储的地址更改了,但堆所占有的内存也需要清除,而清除的方式就是通过垃圾回收机制进行释放内存。

引用计数

计算一个对象被引用的次数进行垃圾回收。对于引用次数为0的对象进行销毁。

这个方法会导致相互引用的变量永远不会被销毁。

标记清除

对于进入执行环境的变量打上标记,离开执行环境的变量则清除标记。清除时,将所有无标记的变量销毁、回收内存。

标记清除实现简单,大部分浏览器的垃圾回收机制都是基于这个方法进行优化。

简单地将变量进行销毁会带来一个问题:剩余的对象内存位置没有变化,只有被销毁的变量内存空闲出来,内存占用不连贯。所以在标记清除之后还需要继续标记整理(Mark-Compact),将剩余占有的内存整理到一起。

V8引擎对标记清除的优化

标记清除需要定期遍历对象,确认是否需要销毁。V8区别开新产生的对象与旧的对象,对他们进行不同的处理。

新生代

新生代用于存储新产生的对象,一般只有1-8M。

堆内存分为两个区域,一个是使用区,一个是空闲区,对象都会存放到使用区中。当使用区满时就会执行一次垃圾回收。

通过标记确认在执行环境内的对象将被复制在空闲区中,然后会清空使用区。这时的空闲区就变成了使用区,使用区变成了空闲区。

多次复制后依然存在的对象就会移动到老生代内存中。或者在复制过程中,占有的内存超过了限制(25%)也会直接移动至老生代。

老生代

老生代直接使用了标记清除进行垃圾回收,标记阶段从一组根元素开始,遍历所有元素增加标记。再对无标记的元素进行销毁。

并行回收

由于js是单线程,所以为了防止垃圾回收阻塞js执行,导致页面卡顿。通过多进程进行并发处理垃圾回收。

增量标记

将垃圾回收的过程细分化,每次进行一部分。

通过三色标记法,可以确认哪个对象还在检测中。

  • 白色代表未被标记
  • 灰色代表自身被标记,但内部还有未被标记的变量
  • 黑色代表自身与内部变量都被标记

这样在执行到中途时就可以暂停,等下次再继续垃圾回收。如果有灰色的节点,表示还需要继续遍历,不存在灰色节点的时候就可以直接进行销毁阶段。

当黑色节点内部存在白色节点,这个白色节点会被修改为灰色。保证当前节点不会在恢复后被销毁。这种方法叫写屏障 (Write-barrier)

惰性清理(Lazy Sweeping)

在销毁阶段也可以分批继续销毁,防止长时间阻塞。

参考链接

「硬核JS」你真的了解垃圾回收机制吗

V8 的并发标记

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容