• golang垃圾回收机制


    golang的GC,1.8通过混合写⼊屏障, 使得STW降到了sub ms。go语言中程序代码执行和垃圾回收是并发执行的。

    当前Go GC特征 :
    三色标记,并发标记和清扫,非分代,非紧缩,混合写屏障。
    三色标记:
    1. 将所有对象放在白色集合中
    2. 从rootset遍历可达对象,将可达对象放在灰色集合中
    3. 将灰色集合中对象进行遍历,将可达对象放在灰色集合中,将其本身放在黑色集合中
    4. 重复第三步,直到灰色集合遍历为空
    5. 将白色集合中的对象视为垃圾进行清扫
    6. 重置黑色集合对象,将其变为白色,进行下次GC

    gc写屏障解决垃圾回收并发的问题:

    写屏障是在写入指针前执行的一小段代码,用以防止并发标记时指针丢失,这段代码Go是在编译时加上的。
    如果以下代码没有写屏障,则当代码执行和垃圾回收并发执行时,GC垃圾回收扫描到obj1为nil,将其标记为回收对象,此时代码重新给obj1和obj2赋值,obj2为nil,垃圾回收将obj2标记为回收对象,此时obj1和obj2都会被回收,但obj1此时是不需要回收的

    func (obj *Object) Demo() {
    //初始化
    obj1 = nil
    obj2 = obj
    //gc 垃圾回收开始⼯作
    //扫描对象 obj1 完成后
    //代码修改为:对象重新赋值
    obj1 = obj
    obj2 = nil
    //扫描对象 obj2
    }


    GC触发
    1. 分配内存时, 当前已分配内存与上一次GC结束时存活对象的内存达到某个比例时就触发GC。
    2. sysmon检测2min内是否运行过GC, 没运行过 则执行GC。
    3. runtime.GC()强制触发GC。

    垃圾回收默认是全并发模式运行,GC goroutine 一直循环执行,直到符合触发条件时被唤醒。

    并发标记分为两个步骤:
    扫描:遍历相关内存区域,依次按照指针标记找出灰色可达对象,加入队列。
    标记:将灰色对象从队列取出,将其引用对象标记为灰色,自身标记为黑色。

    // 将灰色对象从队列取出,其引用对象标灰,自身标黑
    func gcBgMarkStartWorkers() {
    	// Background marking is performed by per-P G's. Ensure that
    	// each P has a background GC G.
    	for _, p := range allp {
    		if p.gcBgMarkWorker == 0 {
    			go gcBgMarkWorker(p)
    			notetsleepg(&work.bgMarkReady, -1)
    			noteclear(&work.bgMarkReady)
    		}
    	}
    }

    垃圾清理
    所有未标记的白色对象不再被引用,可以将其内存回收。

    // 无限循环,被唤醒后执行并发清理任务,完成后回收内存等待下次执行
    func bgsweep(c chan int) {
    	sweep.g = getg()
    
    	lock(&sweep.lock)
    	sweep.parked = true
    	c <- 1
    	goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1)
            
    	for {
    		for sweepone() != ^uintptr(0) {
    			sweep.nbgsweep++
    			Gosched()
    		}
    		for freeSomeWbufs(true) {
    			Gosched()
    		}
    		lock(&sweep.lock)
    		if !isSweepDone() {
    			// This can happen if a GC runs between
    			// gosweepone returning ^0 above
    			// and the lock being acquired.
    			unlock(&sweep.lock)
    			continue
    		}
    		sweep.parked = true
    		goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1)
    	}
    }
  • 相关阅读:
    【CodeForces】835D Palindromic characteristics
    【BZOJ】2006: [NOI2010]超级钢琴
    【比赛】STSRM 09
    【比赛】洛谷夏令营NOIP模拟赛
    【BZOJ】4147: [AMPPZ2014]Euclidean Nim
    【BZOJ】3895: 取石子
    【胡策08】解题报告
    【codevs】3196 黄金宝藏
    【BZOJ】1443: [JSOI2009]游戏Game
    【BZOJ】3105: [cqoi2013]新Nim游戏
  • 原文地址:https://www.cnblogs.com/FG123/p/12828665.html
Copyright © 2020-2023  润新知