Go 内存管理| 青训营笔记

98 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第5天

介绍

通过此篇了解操作系统如何管理内存,看Go语言内部的内存管理。Go的内存管理基本上是参考tcmalloc来实现的。

Go内存管理是自动化的,我们可以直接定义变量使用,不需要考虑变量背后内存的应用和释放问题。

追踪垃圾回收

判断一个对象是否可达,因为一旦这个对象不可达就可以立刻被 GC 回收了。那么我们怎么判断一个对象是否可达呢?

第一步,标记根对象,即找出所有的全局变量和当前函数栈里的变量,常量等,标记为可达;

第二步,从已经标记的数据开始,进一步标记它们可访问的变量,以此类推,专业术语叫传递闭包。

清理所有不可达对象:三种方式,根据对象的生命周期,使用不同的标记和清理策略

  • 标记-复制——将存活对象复制到另外的内存空间(Copying GC)
  • 标记-清除——将死亡对象的内存标记为可分配(Mark-sweep GC):使用free-list管理空闲内存
  • 标记-整理——移动并整理存活对象(Mark-compact GC):原地整理对象

2a1d12e70cd340acbaf18dc1a6198d06_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

逃逸分析

大致思路:从对象分配处出发,沿着控制流,观察对象的数据流,若发现指针 p 在当前作用域 s 出现一下情况:

  1. ​ 作为参数传递给其他函数
  2. ​ 传递给全局变量
  3. ​ 传递给其他的goroutine
  4. ​ 传递给已逃逸的指针指向的对象
  5. ​ 则指针p指向的对象逃逸出 s ,反之则没有逃逸出 s 。

采用函数内联可以使较多的对象难以逃逸

a8b391cff3fd4728adf4e40ec93e8c0c_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

总结

Go内存管理是典型金字塔结构。现在常见的web服务设计,为了提高系统性能,一般都采用金字塔结构设计。

将有限的计算资源排列成金字塔结构,将数据从热到冷分成若干层,放置在金字塔结构上。调度程序不断调整,将热数据放在金字塔的顶部,冷数据放在底部。