go gc

王柳  金牌会员 | 2024-1-24 03:25:22 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 907|帖子 907|积分 2721

垃圾回收 (Garbage Collecting)思路
  1. 1. "标记-清除〞  go的做法
  2. 2. "标记-整理〞  标记后删除, 删除后重新把内存空间整理  java 早期
  3. 3. "标记 - 复制〞  两块相似的内存, 直接把有用的拷贝到另外一块上去  java 现阶段
复制代码
Go因为堆内存结构的独特优势,选择最简单的标记-清除
找到有引用的对象,剩下的就是没有引用的
如何标记

有用的对象从哪里开始找
  1. 1. 被栈上的指针引用 一块堆上对象, 现在被栈上指针引用了, 栈上是正则运行的程序 .
  2. 2. 被全局变量指针引用
  3. 3. 被寄存器中的指针引用 当做参数或者中间变量,放入了寄存器中,也是正则运行的
  4. 上述变量被称为 Root Set (GC Root)
复制代码
搜索算法 有广度优先和深度优先
  1. 广度优先遍历,指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,再依次遍历
  2. 每个相邻节点的相邻节点。
  3. 深度优先从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回
  4. 退到上一个节点,再从另一条路开始走到底...,不断递归重复此过程,直到所有的顶点都遍历完成.
复制代码
三色标记法
  1. 1. 所有的堆对象都是白色的.   
  2. 2.Root set 置为灰色   // 要开始分析 这些对象引用了 上面白色的那些对象
  3. 3. 置为黑色  // 经过分析, 被root 对象直接 或者间接引用了
  4. 4. 最终只会存在 白色 和 黑色两种, 最后一层灰色对象没有引用其他对象,置为黑色
  5. 5. 清理白色对象.
复制代码
串行GC标记 STW
  1.   Stop The World, 暂停所有其他协程
  2.   通过可达性分析,找到无用的堆内存
  3.   释放堆内存
  4.   恢复所有其他协程
复制代码
问题: 暂停了所有协程, 性能不好
并发标记 删除
  1. 归纳下: 当标记开始时, 如果有对象被别的对象删除了, 不引用了, 但是 又被前面已经分析过的对象引用, 就会造成, 误清理.
  2. 解决办法: gc开始后,被删除的对象,置为灰色. 就意味着不光删除对象不会被清理, 而且删除对象引用的对象也不会被清理. 如果确实没有被引用了, 下次gc时候,肯定会被删除.
复制代码
下面图, 表达就是描述的信息:
删除屏障
  1. 并发标记时, 对指针释放的白色对象置灰
复制代码
删除屏障可以杜绝在GC标记中被释放的指针,被清理, 真没被引用了,下次GC会被删除
并发标记 删除

类似上面的 插入 ,基本一个套路.
插入屏障
  1. 并发标记时, 对指针新指向的白色对象置为灰
复制代码
混合屏障
  1.   包含删除和插入.
  2.   被删除的堆对象标记为灰色
  3.   被添加的堆对象标记为灰色
复制代码
GC的触发

1. 系统定时触发
  1.   sysmon定时检查
  2.   如果2分钟内没有过GC,触发
  3.    p0协程一直在检查GC, 发现2分钟没有触发,就会主动触发.
复制代码
在runtime的 proc.go 中有定义:
  1.     // forcegcperiod is the maximum time in nanoseconds between garbage
  2.     // collections. If we go this long without a garbage collection, one
  3.     // is forced to run.
  4.     var forcegcperiod int64 = 2 * 60 * 1e9
复制代码
2. 用户显式触发
  1.   用户调用runtime.GC方法
  2.   并不推荐调用
复制代码
3. 申请内存时触发
  1.   给对象申请堆空间时,可能导致GC
  2. 在mallocgc 中有体现. 有兴趣的可以去看下源码.
复制代码
GC优化原则
  1. 1. 尽量少在堆上产生垃圾
  2. 2. 内存池化
  3.   类似channel的缓存空间  
  4. 3. 减少逃逸
  5.    
  6.     逃逸会使原本在栈上的对象进入堆中, 例如fmt包  返回指针
  7. 4. 使用空结构体
复制代码
GC分析工貝
  1. go tool pprof
  2. go tool trace
  3. go build -gcflags= "m"
  4. GODEBUG =" gctrace=1"  这个最直接
复制代码
GODEBUG  使用


  • run main.go
  1. 这里主要关注 %比, 例如 5%代表 系统有5%的时间,在做GC. gc在标记阶段是并行的, 但是在一些关键节点,还是不能并行.
  2. 这个值如果超过 10%就要排查下问题和优化了.
  3. 4 ->6->5M  GC开始时候 4M 过程中 6M 结束时候 5M
  4. p 是线程的个数
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王柳

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表