前言
Garbage Collection (GC)是⼀种⾃动管理内存的⽅式。⽀持GC的语⾔⽆需⼿动管理内存,程序后
台⾃动判断对象。是否存活并回收其内存空间,使开发⼈员从内存管理上解脱出来。
垃圾回收机制
- 引⽤计数
- 标记清除
- 三⾊标记
- 分代收集
发展
版本 ——发布时间——GC ——————————STW时间
v 1.1 ——2013/5 ——STW ——————————百ms-⼏百ms级别
v 1.3 ——2014/6 ——Mark STW, Sweep 并⾏ — 百ms级别
v 1.5 ——2015/8—— 三⾊标记法, 并发标记清除 -10ms级别
v 1.8 ——2017/2—— hybrid write barrier ————sub ms
三色标记
- 有⿊⽩灰三个集合,初始时所有对象都是⽩⾊
- 从Root对象开始标记, 将所有可达对象标记为灰⾊
- 从灰⾊对象集合取出对象, 将其引⽤的对象标记为灰⾊, 放⼊灰⾊集合, 并将⾃⼰标记为⿊⾊
- 重复第三步, 直到灰⾊集合为空, 即所有可达对象都被标记
- 标记结束后, 不可达的⽩⾊对象即为垃圾. 对内存进⾏迭代清扫,回收⽩⾊对象
- 重置GC状态
混合写屏障
- 并发标记时, 如果没有做正确性保障措施,可能会导致漏标记对象,导致实际上可达的对象被清扫
掉。
在Go语言中,垃圾回收(GC)的混合写屏障(concurrent write barrier)是通过硬件层面的内存访问记录(write barrier)和垃圾回收器的屏障实现的。这是 Go 语言的垃圾回收器的并发标记(concurrent marking)和并发垃圾回收(concurrent garbage collection)机制的一部分。
简要解释一下这些术语:
内存访问记录(write barrier): 写屏障是一种技术,用于追踪在并发环境中对内存的写操作。在Go中,它用于记录对已分配对象的写入,以便垃圾回收器能够感知到这些写入,从而确保在并发标记阶段不会遗漏任何指向对象的引用。
混合写屏障(concurrent write barrier): 在Go语言中,GC采用了一种混合写屏障的方法。这意味着在程序执行的同时,垃圾回收器会通过硬件层面的内存访问记录来捕获对已分配对象的写入,以便并发标记阶段能够正确地追踪对象的引用关系。
混合写屏障的实现利用了现代处理器中的写屏障指令(write barrier instruction),这些指令会在写入内存时触发对应的硬件层面的记录。这样,GC可以在并发执行的程序中准确地追踪对象的引用,而不需要全局停顿。
GC 触发条件
在Go语言中,垃圾回收(GC)的触发条件通常由运行时系统根据当前程序的状态和运行情况来决定。Go语言的GC采用了分代垃圾回收策略,主要分为新生代(young generation)和老年代(old generation),每个代都有不同的触发条件。
以下是触发GC的一般条件:
新生代触发条件:
对象分配: 当程序执行new或make等分配内存的操作时,如果新生代的内存不足,将触发新生代的垃圾回收。
新生代对象晋升: 当新生代中的对象经过一定次数的垃圾回收仍然存活,会晋升到老年代。此时可能会触发老年代的垃圾回收。
老年代触发条件:
老年代对象晋升: 当新生代中的对象晋升到老年代,老年代的内存占用可能达到一定阈值时,会触发老年代的垃圾回收。
周期性触发: 运行时系统会根据一些周期性的策略触发老年代的垃圾回收,以确保内存的合理使用。
在Go语言中,垃圾回收是在程序运行时(concurrent)进行的,因此它是透明的,不会导致全局停顿。GC的目标是最小化对程序的影响,并且只有在必要的情况下才会进行回收操作。
-
gcTriggerHeap
分配内存时, 当前已分配内存与上⼀次GC结束时存活对象的内存达到某个⽐例时就触发GC。
-
gcTriggerTime
sysmon检测2min内是否运⾏过GC, 没运⾏过 则执⾏GC。
-
gcTriggerAlways
runtime.GC()强制触发GC。