Go 内存管理 -- 垃圾回收

前言

go作为一个非常年轻的语言,吸取了各个语言的优点,比如说Java中优秀的垃圾回收,来释放程序员一部分精力。
本篇要说的就是垃圾回收,常见的垃圾回收算法有标记-清除、标记整理、复制,然后在这些算法基础上有分为分代&非分代回收,这些算法都非常优秀,只是面对的场景不同罢了,但是要是想透彻的理解垃圾回收,看Java中的实现再合适不过了,如果能对于Java中的垃圾回收非常熟悉,理解go的垃圾回收将非常简单。
go中的垃圾回收官方是这么描述的:非分代的、非紧缩的、写屏障的并发标记清除的垃圾回收。

标记清除

标记清除指的是对于那些已经不会再使用的对象进行标记,标记完成后,对于标记的对象进行清除。


image.png

很显然如果使用标记清除算法:
1、确定标记的起点GCRoot
2、存在一定的内存碎片
3、效率相对于复制、整理 效率要稍微高一些
但标记清除是最常见的垃圾回收算法,Java 中CMS等垃圾回收器用的就是这个。
在标记的过程中有一个所有垃圾回收算法(涉及GCRoot的初始标记)都有的问题stop-the-world
标记&清理的过程可以是串行的(效率很低),也可以是并发的。

三色标记

三色标记是一种在传统的标记清除算法基础上衍生出来的一个改进的并发标记算法:
1、首先创建三个集合:白、灰、黑
2、将所有对象放入白色集合中
3、然后从根节点开始遍历所有对象(注意这里并不递归遍历),把遍历到的对象从白色集合放入灰色集合。
4、之后遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合
5、重复 4 直到灰色中无任何对象
6、通过write-barrier检测对象有变化,重复以上操作
7、收集所有白色对象(垃圾)


image.png

非常关键的一点是GCRoot的确定,这是整个算法的开端:
当前goroutine的栈和全局数据区中的对象作为GCRoot。

三色标记中的并发标记

所谓的并发标记就是指在goroutine执行的过程中能进行标记行为,这里采用的方式与Java的CMS方式比较像,通过写屏障来保证正确性。
比如说:当从A这个GC root找到引用对象B时,B变灰A变黑。这时用户goroutine执行把A到B的引用改成了A到C的引用,同时B不再引用C。然后GC goroutine又执行,发现B没有引用对象,B变黑。而这时由于A已经变黑完成了扫描,C将当做白色不可达对象被清除,这里就会出现一个不该被清理的对象被清理了。
而写屏障就是在这个出错的地方做了下判断:
当发现A已经标记为黑色了,若A又引用C,那么把C变灰入队。go gc时借助一个队列,也就是gc-work来完成非递归遍历。

强制回收

因为系统启动或者短时间内大量分配对象这些原因,会将垃圾回收的gc_trigger(垃圾回收的触发器)的标准瞬间推高。当服务正常后,活跃对象远小于这个阈值,造成垃圾回收无法触发。
所以需要有一个强制回收的触发,sysmon每隔2分钟强制触发GC一次。强制GC的goroutine一直park在后台,直到sysmon将它唤醒开始执行gc。

GC整体过程

Goff to Gmark
每次的gcstart都是满足gc_triger时由mallocgc触发,整个的启动过程是stop the world的,这个过程启动了所有的GC工作协程,进入GCMark状态使能写屏障,启动gcController。简单来说就是确定GCroot相关的goroutine。
Gmark
这个阶段是标记阶段,拿到准备好的goroutine来做标记,但是一开始就gopark当前的goroutine(上个阶段),直到被gccontroller的findRunnableGCWorker唤醒。
唤醒后进入标记阶段,每个worker都去gc-work中拿节点(节点置黑),然后处理当前节点看有没有指针和没标记的对象,继续入队子节点(灰化节点),直到队列为空。
Gmarktermination
标记结束后调用gcMarkDone
Gsweep
具体的清除行为,有多个时机可以出发Gsweep,如果是并发清除的话,需要先回收未被标记的heap区,然后唤醒进行sweep的 goroutine。
关于整体回收这一块儿内容,大家有兴趣可以看一下源码。
关于go的垃圾回收暂时就先介绍这么多。
关于go的内存管理后续会单独出一个系列,所以本系列仅仅阐述了一个内存管理的梗概和基础概念。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容