GC内存管理机制
Go的GC目前使用的是无分代(对象没有代际之分)、不整理(回收过程中不对对象进行移动和整理)、并发(与用户代码并发执行)的三色标记清扫算法。原因:
-
不整理,对象整理是解决内存碎片问题,但GO运行时的分配算法是基于
tcmalloc
,对对象整理没有实质性能提升。 -
无分代,Go的编译器通过逃逸分析将大部分新生对象存储在栈上,只有需要长期存在的对象才会被分配到需要进行垃圾回收的堆中。也就是说存活时间短的对象在Go中是直接被分配到栈上,当
goroutine
死亡后栈也会被直接回收,不参GC过程。 -
并发,Go团队更关注如何更好地让GC与用户代码并发执行,而非减少STW这一单一目标。
通常,垃圾回收器的执行过程被划分为两个半独立的组件:
- 赋值器(Mutator):这一本质上是指用户态的代码。因为对垃圾回收器而言,用户态的代码仅仅只是在修改对象之前的引用关系,也就是在对象图(对象之间的引用关系的一个有向图)上进行操作。
- 回收器(Collector):负责执行垃圾回收的代码
- 内存分配器(Allocator):在堆上申请内存
- 堆(Heap)
GC常见的方式
- 追踪式GC(Go、Java、JavaScript)
- 引用计数GC(Python、Objective-C)
”GC过程/三色标记法是什么?“
是一种描述追踪式GC的方法,它的作用是从逻辑上严密推导标记清理这种垃圾回收方法的正确性。
当垃圾回收开始时,只有白色对象。随着标记过程开始进行时,灰色对象开始出现(着色),这时候波面便开始扩大。当一个对象的所有子节点均完成扫描时,会被着色为黑色。当整个堆遍历