GO的GC辣鸡回收(一)

用户程序通过内存分配器(Allocator)在堆上申请内存,而垃圾收集器(Collector)负责回收堆上的内存空间,内存分配器和垃圾收集器共同管理程序中的堆内存空间。

基本概念 垃圾分类

语义垃圾:也就是内存泄漏,指的是从语法上可达的对象,也就是被其他对象引用的,但是从语义上来讲是垃圾。这类垃圾,垃圾回收是不管的

语法垃圾:从语法上是不可达的对象,也就是没有对象引用了,这些垃圾是垃圾回收重点照顾的对象

垃圾回收算法

常见的垃圾回收算法:

引用计数:

GO的GC辣鸡回收(一)

某个对象的根引用计数变为0时,其所有节点均需被回收

标记压缩:

GO的GC辣鸡回收(一)

存活对象移动到一起,有效解决内存碎片问题

复制算法:

GO的GC辣鸡回收(一)

将所有正在使用的对象从From空间复制到To空间,堆利用率只有一半,也能解决内存碎片问题

标记清除:

GO的GC辣鸡回收(一)

标记垃圾对象,然后再清除。解决不了内存碎片问题,需要与能尽量避免内存碎片的内存分配器使用,如tcmalloc

标记清除

标记清除算法是最常见的垃圾收集算法,标记清除收集器是跟踪式垃圾收集器,其执行过程可以分为标记、清除两个阶段:

标记阶段:从根对象出发查找并标记堆中所有存活的对象

清除阶段:遍历堆中的全部对象,回收未被标记的垃圾对象并将回收的内存加入空闲链表

传统的标记清除算法,垃圾收集器从垃圾收集的根对象出发,递归遍历这些对象指向的子对象并将所有可达的对象标记成存活。标记结束后,垃圾收集器会依次遍历堆中的对象并清除其中的垃圾,整个过程需要标记对象的存活状态,所以用户程序在垃圾收集的过程中不能执行,也就是常说的STW(Stop The World)

三色抽象

为了解决原始标记清除算法带来的长时间STW,大部分追踪式垃圾收集器都会实现三色标记算法的变种以缩短STW的时间
三色标记算法将程序中的对象分成白色、黑色、灰色:

白色对象:潜在的垃圾,也就是没有被扫到的对象,其内存可能会被垃圾收集器回收

黑色对象:活跃的对象,包括不存在任何引用外部指针的对象以及从根对象可达的对象

灰色对象:活跃的对象,因为存在指向白色对象的外部指针,垃圾收集器会扫描这些对象的子对象

标记过程:
垃圾收集器开始工作的时候,不存在任何黑色对象,根对象会被标记成灰色,垃圾收集器只会从灰色对象集合中取出对象开始扫描,当灰色集合中不存在任何对象时,标记就会结束。

GO的GC辣鸡回收(一)

大致工作原理:

从灰色对象的集合中选择一个灰色对象并将其标记成黑色

将黑色对象指向的所有对象都标记成灰色,保证该对象和被该对象引用的对象都不会被回收

重复上述两个步骤直到不存在灰色对象

当三色标记结束后,应用程序的堆中就不存在任何灰色对象,我们只能看到黑色的存活对象以及白色的垃圾对象,垃圾收集器可以回收这些白色的垃圾。
缺陷:
由于用户程序可能在标记执行的过程中修改对象的指针,所以三色标记清除算法本身是不可以并发或者增量执行的,仍需要STW。如果本来不应该被回收的对象被回收了,这在内存管理中是非常严重的错误,这种错误称为悬挂指针,也就是指针没有指向特定类型的合法对象,影响了内存的安全性,想要并发或者增量标记对象就需要使用屏障技术。

屏障技术

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgfjfd.html