美文网首页
go 混合写屏障

go 混合写屏障

作者: overflow_e4e4 | 来源:发表于2023-01-27 17:19 被阅读0次

go 混合写屏障:

  1. GC开始时,STW,对栈进行扫描,将所有可达对象置黑
  2. GC期间,任何栈上新创建的对象,皆置黑【1和2配合,可避免插入屏障对栈区的二次三色标记】
  3. 被删除的对象置灰
  4. 新挂载的对象置灰

疑问:栈上的对象如果是随着栈回收而被回收的话,为啥混合写屏障还会有对栈上内存的规则?
答案:(疑似)
Go语言中实际的栈帧布局如下所示(源代码中的注释):


image.png image.png

运行时可以计算出当前栈帧的函数参数、函数本地变量、寄存器信息SP、BP等一系列信息。

对每一个栈帧函数中的参数和局部变量,都需要对其进行扫描,扫描该对象是否仍然在使用。如果在使用,需要扫描bytedata位图判断对象中是否包含指针,如果包含指针则需要进行标记。其中函数执行到某一位置时,与某个参数和局部变量对应的位图bytedata是借助于编译时计算出来的。

func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) {
    // 扫描局部变量
    if locals.n > 0 {
            size := uintptr(locals.n) * sys.PtrSize
            scanblock(frame.varp-size, size, locals.bytedata, gcw, state)
        }

    // 扫描函数参数
        if args.n > 0 {
            scanblock(frame.argp, uintptr(args.n)*sys.PtrSize, args.bytedata, gcw, state)
        }
}

什么情况下对象可能没有在使用了呢?例如如下所示,当foo()函数执行到调用bar() 函数时,局部对象t就已经没有被使用了,所以即便对象t中有指针,位图bytedata中全为0,代表参数不再被使用。一个不再被使用的对象,可以被回收,不需要再进行扫描。

func  foo(){
     t := T{}
     t.a = 2
   bar()
}

栈对象(stack object)

在Go语言早期就是通过上述方式对协程栈中的对象进行扫描的。但是这种方法在有些情况下会出现问题,例如在如下函数中, 对象t首先被p所引用,但是在之后的程序中,变量p的值发生了变化,这意味着,t其实并没有使用了。但是编译器由于难以知道P在何时会重新赋值导致t不再被引用,因此,编译器会采取保守的策略认为t对象仍然存在,从而,如果对象t中有指针指向了堆内存,就造成了内存泄露问题。因为这部分内存本应该被释放。

t := T{...}
p := &t
for {
    if … {
         p = … 
    }
}

为了解决内存泄露的问题,Go语言引进了 栈对象(stack object) 的概念。栈对象是在栈上能够被寻址的对象。例如上例中的t,由于其能够被&t的形式寻址,其一定在栈上有地址。所以t就被叫做 栈对象。因为并不是所有的变量都会存储在栈上,例如存储在寄存器中的变量就是不能被寻址的。

首先,编译器会在编译时将所有的栈对象记录下来,在垃圾回收期间,所有的栈对象会存储到一颗二叉搜索树中。接着,第二步将栈中所有可能指向栈对象的指针都进行追踪。

如下所示,假设F为一个局部变量指针,其引用了栈帧上的栈对象E→C→D→A, 因此说明栈对象E、C、D、A都是存活的,需要被扫描。 相反如果栈对象B没有被扫描,并且接下来在foo()函数中没有使用到B对象,那么B栈对象不会被扫描,从而解决了内存泄露问题。

参考:
https://zhuanlan.zhihu.com/p/321581866
https://cloud.tencent.com/developer/article/1583077

相关文章

  • go语言 GC混合写屏障

    golang混合写屏障实现 写屏障只应用在堆上应用,栈上部启用。 GC开始将栈上的对象全部扫描并标记为黑色。 GC...

  • go三色回收(二)

    存在的问题 为什么必须三色,二色的话会有什么问题 插入写屏障为什么不行 为什么必须使用混合写屏障,删除写屏障为什么...

  • go gc垃圾回收——三色标记、混合写屏障

    一、什么是GC 垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自...

  • Golang垃圾回收机制

    原文链接 :[典藏版]Golang三色标记、混合写屏障GC模式图文全分析[https://www.jianshu....

  • Go: 屏障并发模式

    什么是屏障并发模式? 假设有这么一种场景,一个微服务需要调其他两个微服务的响应结果来返回结果给客户端。屏障并发模式...

  • Golang之GC

    参考 图解Golang的GC算法 搞懂Go垃圾回收 Golang垃圾回收 屏障技术

  • 所谓“护肤”护的是什么?

    皮肤屏障,广义包括物理屏障、色素屏障、神经屏障、免疫屏障。 而我们平时说起的皮肤屏障主要指的是“狭义屏障”-物理屏...

  • 皮肤屏障为什么会受损?

    我们的皮肤屏障 为什么会受损呢? 皮肤屏障广义包括物理屏障、色素屏障、神经屏障、免疫屏障。皮肤屏障狭义主要指物理性...

  • Golang GC算法

    概括 Go的垃圾回收官方形容为 非分代 非紧缩 写屏障 三色并发标记清理算法。非分代:不像Java那样分为年轻代和...

  • 合写

    这么说吧,我是一个界限分明的人,当然也有很多时候我不是,但这正是我界限分明的另一种写照,就像有的时候我感到我是我,...

网友评论

      本文标题:go 混合写屏障

      本文链接:https://www.haomeiwen.com/subject/vgtpqdtx.html