• golang gc 原理和内存分配


    更好的阅读体验建议点击下方原文链接。
    原文地址:http://maoqide.live/post/golang/golang-gc-memory-allocation/

    关于 Golang GC 和内存管理相关的流程和原理的一些总结。

    GC 流程

    golang GC 采用基于标记-清除的三色标记法,下图为 golang 一轮完整的 GC 的过程:

    一轮完整的 GC,总是从 Off,如果不是 Off 状态,则代表上一轮GC还未完成,如果这时修改指针的值,是直接修改的。

    Stack scan: 收集根对象(全局变量和 goroutine 栈上的变量),该阶段会开启写屏障(Write Barrier)。

    Mark: 标记对象,直到标记完所有根对象和根对象可达对象。此时写屏障会记录所有指针的更改(通过 mutator)。

    Mark Termination: 重新扫描部分全局变量和发生更改的栈变量,完成标记,该阶段会STW(Stop The World),也是 gc 时造成 go 程序停顿的主要阶段。

    Sweep: 并发的清除未标记的对象。

    三色标记

    以上 Mark 阶段,采用的是三色标记法,是传统标记-清除算法的一种优化,主要思想是增加了一种中间状态,即灰色对象,以减少 STW 时间。
    三色标记将对象分为黑色、白色、灰色三种:

    • 黑色:已标记的对象,表示对象是根对象可达的。
    • 白色:未标记对象,gc开始时所有对象为白色,当gc结束时,如果仍为白色,说明对象不可达,在 sweep 阶段会被清除。
    • 灰色:被黑色对象引用到的对象,但其引用的自对象还未被扫描,灰色为标记过程的中间状态,当灰色对象全部被标记完成代表本次标记阶段结束。

    三色标记的主要过程即:

    1. 开始时所有对象为白色
    2. 将所有根对象标记为灰色,放入队列
    3. 遍历灰色对象,将其标记为黑色,并将他们引用的对象标记为灰色,放入队列
    4. 重复步骤 3 持续遍历灰色对象,直至队列为空
    5. 此时只剩下黑色对象和白色对象,白色对象即为下一步需要清除的对象

    STW

    传统的标记-清除算法,为了防止在标记过程中,对象引用发生变化,导致清除仍在使用的对象,需要 STW(Stop The World),这会造成程序的停顿。在三色标记的过程中,由于引入了灰色对象这一中间状态,标记过程和用户的 golang 代码中可以并发执行,不需要 STW,这极大的减少了应用的停顿时间。
    三色标记具体如何避免在标记过程中对象应用的改变呢,这里用到了写屏障(Write Barrier)。

    写屏障

    在 GC 的流程中,Stack scan 这一步骤,启用了写屏障。写屏障的主要思想,是在标记的过程中,通过写屏障记录发生变化的指针,然后在 Mark termination 的 rescan 过程中,重新进行扫描,因为在这一步骤会 STW,所以在这一步骤完成后的白色对象,不会再被引用,可以直接清除。关于写屏障具体原理和实现,这里不再展开。

    GC触发

    golang 程序的执行过程中,如下几种情况下会触发 GC:

    • 主动触发,用户代码中调用 runtime.GC 会主动触发 GC
    • 默认每 2min 未产生 GC 时,golang 的守护协程 sysmon 会强制触发 GC
    • 当 go 程序分配的内存增长超过阈值时,会触发 GC

    内存分配

    golang 内存分配分为堆内存和栈内存。
    栈:一般函数内部执行中声明的变量,函数返回直接释放,不会引起垃圾回收,对性能无影响。
    堆:有引用到的内存空间,靠 GC 回收,会影响程序进程。

    内存逃逸

    逃逸分析是指由编译器决定内存分配的位置,不需要程序员指定。即由编译器决定新申请的对象会分配到堆上还是栈上。
    逃逸分析场景:

    1. 指针逃逸
      go 将函数内定义的变量返回到函数外,会将本应分配到栈上的内存分配到堆上。
    2. 栈空间不足逃逸
      当栈空间不足或无法判断当前切片长度时会将对象分配到堆上。
    3. 动态类型逃逸
      当函数参数为 interface 类型,编译期间无法确定参数的具体类型,也可能会产生逃逸。

    参考列表

  • 相关阅读:
    Python3-shutil模块-高级文件操作
    Python3-sys模块-解释器相关参数与函数
    Python3-os模块-操作系统的各种接口
    Python3-算法-冒泡排序
    Python3-re模块-正则表达式
    Python3-算法-递归
    Python3-设计模式-迭代器模式
    Python3-设计模式-装饰器模式
    PTA 7-28 搜索树判断(镜像二叉搜索树的后序遍历)
    PTA 7-26 Windows消息队列(小顶堆+输入优化)
  • 原文地址:https://www.cnblogs.com/maoqide/p/12355565.html
Copyright © 2020-2023  润新知