go的GC

Go的协程栈的位置

  • Go的协程栈位于Go的堆内存上

  • Go堆内存位于操作系统的虚拟内存上

  • 协程栈记录了协程的执行现场

  • 协程栈负责记录局部变量,传递参数和返回值

  • Go使用参数拷贝传递

逃逸分析

逃逸分析是编译器在编译阶段对变量的生命周期进行分析,判断变量是在栈上还是堆上分配空间。逃逸分析的主要目的是优化内存的分配和减少垃圾回收的压力

  • 栈帧回收后,需要继续使用的变量

  • 变量太大了,栈里面放不下,放到堆里面去

  • 指针逃逸

  • 空接口逃逸

    • 如果函数的参数位interface{}
    • 函数的实参很可能会逃逸
    • 因为interface{}类型的函数往往会使用反射
  • 大变量逃逸

make && new

串行GC

Go使用 标记-删除 ,找到有引用的对象,剩下的就是没有引用的

GC-root是什么

  • 被栈上的指针引用
  • 被全局变量指针引用
  • 被寄存器中的指针引用
  • 上述为 GC-root

串行GC步骤

  • stop the world,暂停所有其他协程
  • 通过可达性分析,找到无用的堆内存
  • 释放无用的堆内存
  • 恢复所有其他协程

image-20240225094832891

Mark Sweep的缺点

  • STW,stop the world;让程序暂停,程序出现卡顿 **(重要问题)**;
  • 标记需要扫描整个heap;
  • 清除数据会产生heap碎片。

三色标记法

  • 黑色:有用,已经分析扫描
  • 灰色:有用,还未分析扫描
  • 白色:暂时无用

混合屏障

删除屏障

  • 并发标记时
  • 对指针释放的白色对象置灰

防止释放的元素A被另一个元素B指向,但元素A被GC的情形

插入屏障

  • 并发插入时
  • 对插入的白色标记置灰

防止 新插入的元素被GC

GC的触发时机

  • 系统定时触发

  • 用户显示触发

  • 申请内存时触发

GC的优化原则

  • 尽量少在堆上产生垃圾
    • 内存池化(类似channel的ring buffer)
    • 减少内存逃逸
    • 使用空结构体

GC的分析工具

  • go tool pprof
  • go tool trace
  • go build -gcflags=” -m”
  • GODEBUF=” gctrace=1”

go的GC
http://example.com/2024/02/25/go的GC/
作者
Forrest
发布于
2024年2月25日
许可协议