这是我参与「第五届青训营」伴学笔记创作活动的第5天
介绍
通过此篇了解操作系统如何管理内存,看Go语言内部的内存管理。Go的内存管理基本上是参考tcmalloc来实现的。
Go内存管理是自动化的,我们可以直接定义变量使用,不需要考虑变量背后内存的应用和释放问题。
追踪垃圾回收
判断一个对象是否可达,因为一旦这个对象不可达就可以立刻被 GC 回收了。那么我们怎么判断一个对象是否可达呢?
第一步,标记根对象,即找出所有的全局变量和当前函数栈里的变量,常量等,标记为可达;
第二步,从已经标记的数据开始,进一步标记它们可访问的变量,以此类推,专业术语叫传递闭包。
清理所有不可达对象:三种方式,根据对象的生命周期,使用不同的标记和清理策略
- 标记-复制——将存活对象复制到另外的内存空间(Copying GC)
- 标记-清除——将死亡对象的内存标记为可分配(Mark-sweep GC):使用free-list管理空闲内存
- 标记-整理——移动并整理存活对象(Mark-compact GC):原地整理对象
逃逸分析
大致思路:从对象分配处出发,沿着控制流,观察对象的数据流,若发现指针 p 在当前作用域 s 出现一下情况:
- 作为参数传递给其他函数
- 传递给全局变量
- 传递给其他的goroutine
- 传递给已逃逸的指针指向的对象
- 则指针p指向的对象逃逸出 s ,反之则没有逃逸出 s 。
采用函数内联可以使较多的对象难以逃逸
总结
Go内存管理是典型金字塔结构。现在常见的web服务设计,为了提高系统性能,一般都采用金字塔结构设计。
将有限的计算资源排列成金字塔结构,将数据从热到冷分成若干层,放置在金字塔结构上。调度程序不断调整,将热数据放在金字塔的顶部,冷数据放在底部。