上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
3.2 初始化
垃圾回收器相关设定和初始化。
// 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论