返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

3.2 初始化

发布于 2024-10-12 19:15:56 字数 4161 浏览 0 评论 0 收藏 0

垃圾回收器相关设定和初始化。

// mgc.go

func gcinit() {
    
	// No sweep on the first cycle.
	sweep.active.state.Store(sweepDrainedMask)

	// Initialize GC pacer state.
	// Use the environment variable GOGC for the initial gcPercent value.
	gcController.init(readGOGC())
}

刚启动,暂时没有后台清理工作,重点是回收控制器的初始化。

// mgcsweep.go

var sweep sweepdata

// State of background sweep.
type sweepdata struct {

	// active tracks outstanding sweepers and the sweep
	// termination condition.
	active activeSweep
}
// mgcpacer.go

// gcController implements the GC pacing controller that determines
// when to trigger concurrent garbage collection and how much marking
// work to do in mutator assists and background marking.

var gcController gcControllerState

重新设计的 PacerRedesign 作为体验功能被开启。鉴于其尚未稳定,暂时不做深入研究。

goexperiment: go/src/internal/goexperiment/flags.go

func (c *gcControllerState) init(gcPercent int32) {
	c.heapMinimum = defaultHeapMinimum

	if goexperiment.PacerRedesign {
		c.consMarkController = piController{
			kp: 0.9,
			ti: 4.0,
			tt:  1000,
			min: -1000,
			max: 1000,
		}
	} else {
		c.triggerRatio = 7 / 8.0
		c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio))
	}

	c.setGCPercent(gcPercent)
}

初始设定的触发大小是 4 MB。当然,GOGC 会影响实际触发阈值。

type gcControllerState struct {

	// Initialized from GOGC. GOGC=off means no GC.
	gcPercent atomic.Int32
    
	// heapMinimum is the minimum heap size at which to trigger GC.
	// For small heaps, this overrides the usual GOGC*live set rule.
	//
	// During initialization this is set to 4MB*GOGC/100. 
	heapMinimum uint64
    
	// triggerRatio is the heap growth ratio that triggers marking.
	//
	// E.g., if this is 0.6, then GC should start when the live
	// heap has reached 1.6 times the heap size marked by the
	// previous cycle. This should be ≤ GOGC/100 so the trigger
	// heap size is less than the goal heap size. This is set
	// during mark termination for the next cycle's trigger.
	//
	// Used if !goexperiment.PacerRedesign.
	triggerRatio float64    
}
// setGCPercent updates gcPercent and all related pacer state.
// Returns the old value of gcPercent.

func (c *gcControllerState) setGCPercent(in int32) int32 {

	out := c.gcPercent.Load()
    
	if in < 0 {
		in = -1
	}
    
	c.heapMinimum = defaultHeapMinimum * uint64(in) / 100
	c.gcPercent.Store(in)
    
    // 计算触发阈值。
	c.commit(c.triggerRatio)

	return out
}
// commit recomputes all pacing parameters from scratch, namely
// absolute trigger, the heap goal, mark pacing, and sweep pacing.
//
// If goexperiment.PacerRedesign is true, triggerRatio is ignored.
//
// This depends on gcPercent, gcController.heapMarked, and
// gcController.heapLive. These must be up to date.

func (c *gcControllerState) commit(triggerRatio float64) {

	if !goexperiment.PacerRedesign {
		c.oldCommit(triggerRatio)
		return
	}

    // 下一轮 GC 目标。(增长 1x)
	goal := ^uint64(0)
	if gcPercent := c.gcPercent.Load(); gcPercent >= 0 {
		goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(gcPercent)/100
	}

    // 一系列影响触发阈值的因素参与计算 ...

    // For small heaps, set the max trigger point at 95% of the heap goal.
	// This ensures we always have *some* headroom when the GC actually starts.
	// For larger heaps, set the max trigger point at the goal, minus the
	// minimum heap size.
    
    minTrigger := c.heapMinimum
	maxTrigger := maxRunway + c.heapMarked
    
	var trigger uint64
	runway := uint64((c.consMark * (1 - gcGoalUtilization) / (gcGoalUtilization)) * float64(c.lastHeapScan+c.stackScan+c.globalsScan))

    if runway > goal {
		trigger = minTrigger
	} else {
		trigger = goal - runway
	}
    
	if maxTrigger < minTrigger { maxTrigger = minTrigger  }    
	if trigger < minTrigger { trigger = minTrigger }
	if trigger > maxTrigger { trigger = maxTrigger }    
	if trigger > goal { goal = trigger }

    // 实际触发阈值。
	c.trigger = trigger
	atomic.Store64(&c.heapGoal, goal)

	// Update mark pacing.
	if gcphase != _GCoff {
		c.revise()
	}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文