垃圾回收(Garbage Collection,简称GC)是编程语言中自动的内存管理机制,垃圾回收,垃圾指的是不再需要的内存块,如果不及时清理就没有办法再利用。
常见的垃圾回收算法有:
引用计数:每个对象维护一个引用计数,如果这个对象被销毁,则计数 -1 ,当计数为 0 时,回收该对象。
优点:对象可以很快被回收,不会出现内存耗尽或到达阀值才回收。
缺点:不能很好的处理循环引用
标记-清除:从根变量开始遍历所有引用的对象,引用的对象标记“被引用”,没有被标记的则进行回收。
优点:解决了引用计数的缺点。
缺点:需要 STW(stop the world),暂时停止程序运行。
分代收集:按照对象生命周期长短划分不同的代空间,生命周期长的放入老年代,短的放入新生代,不同代有不同的回收算法和回收频率。
优点:回收性能好
缺点:算法复杂
此算法是在Go V1.3 之前使用的,主要有两个主要的步骤:
标记(Mark phase)——》清除(Sweep phase)
1 . 暂停程序业务逻辑, 找出不可达的对象,然后做上标记。
注意:mark and sweep 算法在执行的时候,需要程序暂停!也就是所谓的 STW(stop the world)。这段时间程序会卡住。
程序可达对象为 1、2、4
2 . 开始标记,找出所有可达的对象,并标记
对象 1、2、4 做上标记
3 . 清除未被标记的对象
4 . 程序暂停取消。然后重复上面的过程,直至程序生命周期结束。
此算法是在Go V1.5 开始使用的,三色只是为了叙述上方便抽象出来的一种说法,实际上对象并没有颜色之分。这里的三色,对应了垃圾回收过程中对象的三种状态:
1 . 初识阶段,所以对象均为白色,调用情况为:
root ->A->B/A->C/A<->D; root->F; E; G->H;
2 . GC 开始扫描,从根节点开始遍历,发现只有 A 和 F 是根节点,于是将 A、F 从变为灰色对象。 3 . GC 继续扫描灰色对象,会将灰色对象的节点中引用的节点也变为灰色对象,A 节点引用的节点B、C、D 会被变为灰色对象,接着 A 的所有子节点遍历完毕,便会变为黑色对象,而 F 节点没有子节点,也会变为黑色对象。
4 . GC 会循环遍历灰色对象,直到灰色对象之中没有节点为止,在本例中,发现B、C、D 都没有子节点是白色,便将B、C、D 都变为黑色对象。
5 . 剩下E、G、H 为白色对象,GC 便进行回收这些白色对象。
6 . 上面的垃圾回收结束之后,GC 会在进行一步操作,也就是将黑色对象重新变色成白色对象,供下一次垃圾回收使用。
Golang 中的 STW(Stop The World)是停掉所有的 goroutine,专心做垃圾回收,待垃圾回收结束后再恢复 goroutine。STW 时间的长短直接影响了应用的执行,时间过长对于一些web 应用来说是不可接受的,这也是广受诟病的原因之一。为了缩短 STW 的时间,Golang 不断优化垃圾回收算法,这种情况得到了很大的改善。
STW 目的是防止 GC 扫描时内存变化而停掉 goroutine,而写屏障就是让 goroutine 与GC同时运行的手段。虽然写屏障不能完全消除STW,但是可以大大减少STW的时间。写屏障类似一种开关,在 GC 的特定时机开启,开启后指针传递时会把指针标记,即本轮不回收,下次 GC 时再确定。GC 过程中新分配的内存会被立即标记,用的并不是写屏障技术,也即GC过程中分配的内存不会在本轮GC中回收。
为了防止内存分配过快,在 GC 执行过程中,如果 goroutine 需要分配内存,那么这个 goroutine 会参与一部分GC的工作,即帮助 GC 做一部分工作,这个机制叫作 Mutator Assist。
阀值 = 上次GC内存分配量 * 内存增长率
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8