1. golang垃圾回收
golang的垃圾回收算法是三色标记法,其中三个颜色分别为:灰色、黑色、白色,其对应了垃圾回收过程中变量的三种状态:
1.1 垃圾回收流程
假设现在有这么几个对象:
有A-F六个对象,根对象a b为栈区分配的局部变量,根对象a b分别引用了对象 A B,而对象B有引用了对象D
下面简单看一下这几个对象的回收流程:
(1) 初始化:初始化时所有的对象都是白色
(2) 扫描:开始扫描根对象a b,由于a b引用了A B,所以A B设置为灰色
(3) 分析:分析对象A,A没有引用其他对象,将A设置为黑色,B引用了D对象,则将B设置为黑色的同时,将D设置为灰色
(4)结束:重复步骤3,直到灰色队列为空,这时黑色队列中的对象会被保留,白色队列会被回收
1.2 GC原理
GC的原理简单来讲就是标记内存中哪些还在使用,哪些不被使用,而不被使用的部分就是GC的对象。
root区域主要是指程序运行到当前时刻的栈和全局数据区域,是正在使用到的内存,当然应该优先标记,而考虑到内存块中可能存放的事指针,所以开需要扫描灰色队列进行递归标记,待灰色队列为空,就可以将白色标记回收
1.3 GC优化
golang的垃圾回收算法属于标记-清除,是需要STW的,在golang中就是要停掉所有goroutine,进行垃圾回收,待垃圾回收结束后再恢复goroutine。
所以,STW时间的长短直接影响了应用的执行,为了缩短STW时长,golang优化的GC算法,其中写屏障和辅助GC就是两种优化垃圾回收的方法
写屏障:
STW的目的是为了防止GC在扫描时出现内存变化而产生混乱,写屏障就是让goutine和GC同时运行,虽然不能完全消除STW,但可以大幅端减少STW时长。
写屏障在GC的特定时间开启,开启后指针传递时会把指针标记,即本轮不回收,下次GC时再确定。
辅助GC:
为了防止内存分配过快,在GC执行过程中,GC过程中mutator线程会并发运行,而mutator assisit机制会协助GC做一部分的工作。
1.4 GC触发机制
1.5 GC调优
2. 内存逃逸分析
golang中堆栈对于程序员是透明的,栈空间回收更快,堆空间需要触发GC。
逃逸分析,可以尽量把那些不需要分配到堆上的变量直接分配到栈上。
2.1 逃逸分析
逃逸分析一个最基本的原则就是:如果一个函数返回对一个变量的引用,那么它就会发生逃逸
逃逸的常见情况:
2.2 如何避免内存逃逸