go小白入门 | 青训营笔记

106 阅读2分钟

青训营课程笔记

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天,今日主要学习了内存自动管理和优化方面的知识,着重学习了balanced GC优化对象分配和beast mode提升代码质量的相关实战案例。

内存管理及优化

go需要提前把内存分块,为了对象在heap上分配内存。同时关注到对象分配是高频操作每秒分配gb级别的内存,而在昨天学习的pprof是分配对象最常见的函数之一。

balanced GC

GAB对于go内存管理来说是一个大对象,实质是把小对象分配合并成大对象来减小占用率,方法是用copying GC的算法来管理小对象,根据生命周期不同,使用不同标记和清理策略。其中GC算法具有不能回收存活的对象; 吞吐率;业务是否感知;GC元数据开销;追踪垃圾回收;引用计数等特征。

go编译器优化

编译器优化可以真正做到在用户不受影响的同时,提高性能。一般思路是:用编译时间换取更高效的机器码.Beast mode、函数内联、逃逸分析。让我们看一下函数内联怎么影响性能——这边用到micro-benchmark验证。

func BenchmarkInline(b *testing.B){
  ×:= genInteger()
  y := genIntegerO()
  for i := 0; i< b.N; i++ {
  addInline(x, y)
 }
}
func addInline(a, b int) int {
return a + b
func BenchmarkInlineDisabled(b *testing.B) {
   ×:=genInteger()
   y :=genInteger()
   for i := 0; i< b.N; i++ {
     addNoInline(x, y)
   }
}
func addNoInline(a, b int) int{
    return a + b
}

运行之后对比可以看到性能提升了不少,函数的内联大多情况是正向优化的

Beast Mode

在降低函数调用的开销的同时,增加逃逸分析,优化后未逃逸对象可以在栈上分配,内存使用降低了3%。具体实现总结后得到大致思路:从对象分配处出发,沿着控制流,观察对象的数据流,若发现指针p在当前作用域s,作为参数传递给其他函数,传递给全局变量,传递给其他的goroutine,传递给已逃逸的指针指向的对象,则指针p 指向的对象逃逸出s,反之则没有逃逸出s。