golang gc介绍

何为GC?

GC:Garbage Collection(垃圾回收)
垃圾指内存中不再使用的内存区域,自动发现与释放这种内存区域的过程就是垃圾回收。

常见的垃圾回收机制:引用计数(python)、标记-清除(go)、分代收集(JAVA)。
引用计数:对每个对象维护一个引用计数,当引用该对象的对象被摧毁时,引用计数减一,引用计数为零时回收该对象。

标记-清除:从根变量开始遍历所有引用的对象,引用的对象标记为“被引用”,没有被标记的进行回收。

分代收集:按照对象生命周期长短划分不同的代空间,生命周期长的放入老年代,而短的放入新生代,不同代有不同的回收算法和回收频率。

为什么要有GC?

程序运行过程中会申请大量的内存空间,但内存资源是有限的,而对于一些无用的内存空间如果不及时清理的话会导致内存使用殆尽(内存溢出),导致程序崩溃,因此管理内存是一件重要且繁杂的事情
而垃圾回收可以让内存重复使用,并且减轻开发者对内存管理的负担,减少程序中的内存问题。

Go垃圾回收发展史
版本 发布时间 GC算法 STW时间 重大更新
V1.1 2013/5 STW 可能秒级别
V1.3 2014/6 Mark和Sweep分离,Mark、STW、Sweep并发 百ms级别
V1.4 2014/12 runtime代码基本都由C和少量汇编改为Go和少量汇编, 包括GC部分, 以此实现了准确式GC,减少了堆大小, 同时对指针的写入引入了write barrier, 为1.5铺垫 百ms级别
V1.5 2015/8 三色标记法,并发Mark,并发Sweep。非分代、非移动、并发的收集器 10ms-40ms级别 重要更新版本,生产上GC基本不会成为问题
V1.6 2016/2 1.5中一些与并发GC不协调的地方更改。集中式的GC协调协程,改为状态机实现 5-20ms
V1.7 2016/8 GC时栈收缩改为并发,span中对象分配状态由freelist改为bitmap 1-3ms左右
V1.8 2017/2 hybird write barrier,消除了STW中的重新扫描栈 sub ms Golang GC进入Sub ms时代
golang gc 触发条件
GC调用方式 所在位置 代码
定时调用 runtime/proc.go:forcegchelper() gcStart(gcTrigger{kind: gcTriggerTime, now: nanotime()})
分配内存时调用 runtime/malloc.go:mallocgc() gcTrigger{kind: gcTriggerHeap}
手动调用 runtime/mgc.go:GC() gcStart(gcTrigger{kind: gcTriggerCycle, n: n + 1})
STW(stop the world)

STW的过程中,CPU不执行用户代码,全部用于垃圾回收

Root对象

根对象是mutator不需要通过其他对象就可以直接访问到的对象. 比如全局对象, 栈对象, 寄存器中的数据等. 通过Root对象, 可以追踪到其他存活的对象.

可达性

即通过对Root对象能够直接或者间接访问到.

image
Mark(标记)

GC 开始,从 root 开始一层层扫描,扫描过程中把能被触达的 object 标记出来,那么堆空间未被标记的 object 就是垃圾了

Sweep(清除)

遍历堆空间所有 object 对未标记的 object 进行清除,清除完成则表示 GC 完成。

golang gc 演变过程

Go 1.1 GC过程
image.png
Go 1.3 GC过程
image.png
Go 1.5 GC过程

引入三色并发标记法,三色标记法过程如下。
step1:就是只要是新创建的对象,默认的颜色都是标记为【白色】
step2:GC回收开始,然后从根节点开始遍历所有对象,把遍历到的对象从【白色】集合放入【灰色】集合
step3:遍历【灰色】集合,将【灰色】对象引用的对象从【白色】集合放入【灰色】集合,之后将此【灰色】对象放入【黑色】集合
step4:重复第三步, 直到灰色中无任何对象
step5:回收所有的白色标记表的对象. 也就是回收垃圾

三色法动态图
image
image.png
1. 正常情况下,写操作就是正常的赋值。
2. GC 开始,开启写屏障等准备工作。开启写屏障等准备工作需要短暂的 STW。
3. Stack scan 阶段,从全局空间和 goroutine 栈空间上收集变量。
4. Mark 阶段,执行上述的三色标记法,直到没有灰色对象。
5. Mark termination 阶段,开启 STW,回头重新扫描 root 区域新变量,对他们进行标记。
6. Sweep 阶段,关闭 STW 和 写屏障,对白色对象进行清除。
写屏障(write barrier)

这里就需要了解一下写屏障的概念。这也是golang1.8如何去除Mark termination的关键。写屏障的目标就是要保障约束: 黑色对象不会指向白色对象,如果被指向了就会出现被清除的白色对象,实际是被引用的对象,造成错误的清理

写屏障的实现有很多模式,在golang1.7之前主要采用的是Dijkstra-style insertion write barrier,其伪码实现如下:

writePointer(slot, ptr):
    shade(ptr)
    *slot = ptr

其思路就是在进行指针的重定向时,将被指向的指针对象标记为灰色(shade it),这样如果有新的对象被创建或者黑色对象指向白色对象时,目标对象就会标灰,从而满足了黑色对象不会指向白色对象的约束。

“强-弱” 三色不变式
  • 强三色不变式

不存在黑色对象引用到白色对象的指针

image
  • 弱三色不变式

所有被黑色对象引用的白色对象都处于灰色保护状态

image

为了遵循上述的两个方式,Golang团队初步得到了如下具体的两种屏障方式“插入屏障”, “删除屏障”。

Go 1.8 GC过程

三色标记方式,需要在最后重新扫描一下所有全局变量和 goroutine 栈空间,如果系统的 goroutine 很多,这个阶段耗时也会比较长,甚至会长达 100ms。毕竟 Goroutine 很轻量,大型系统中,上百万的 Goroutine 也是常有的事儿。

Go 在1.8 版本使用混合写屏障(hybrid write barrier)机制,将第一次短暂的 STW取消了,在1.9 版本又大大减少了第二次的STW。

大致如下图所示:

GC开始,默认都是白色

image.png

扫描栈区,将可达对象全部标记为黑

image.png

Golang中的混合写屏障满足弱三色不变式,结合了删除写屏障和插入写屏障的优点,只需要在开始时并发扫描各个goroutine的栈,使其变黑并一直保持,这个过程不需要STW,而标记结束后,因为栈在扫描后始终是黑色的,也无需再进行re-scan操作了,减少了STW的时间

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

推荐阅读更多精彩内容