[ Go 语言内存管理详解| 青训营笔记]

62 阅读2分钟

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

性能优化层面

  1. 业务优化
    1. 针对特定场景,具体问题,具体分析
    2. 容易获得较大性能收益
  2. 语言运行时优化
    1. 解决更通用的性能问题
    2. 考虑更多场景
    3. Tradeoffs
  3. 数据驱动
    1. 自动化性能分析工具 - pprof
    2. 依靠数据而非猜测
    3. 首先优化最大瓶颈

性能优化与软件质量

  1. 软件质量至关重要
  2. 在保证接口稳定的前提下改进具体实现
  3. 测试用例: 覆盖尽可能多的场景,方便回归
  4. 文档: 做了什么,没做什么,能达到怎样的效果
  5. 隔离: 通过选项控制是否开启优化
  6. 可观测: 必要的日志输出

自动内存管理(垃圾回收)

概念

  1. Mutator: 业务线程,分配新对象,修改对象指向关系
  2. Collector: GC 线程,找到存活对象,回收死亡对象的内存空间
  3. Serial GC: 只有一个 collector
  4. Parallel GC: 支持多个 collectors 同时回收的 GC 算法
  5. Concurrent GC: mutator(s) 和 collector(s) 可以同时执行

追踪垃圾回收

  1. 被回收条件:指针指向关系不可达对象
  2. 标记根对象
  3. 标记:找到可达对象
  4. 清理:所有不可达对象
    1. Copying GC:将存活对象复制另外的内存空间
    2. Mark-sweep GC:将死亡对象的内存标记可分配
    3. Mark-compact GC:将存活对象移动到最左边
    4. 分代GC:对年轻和老年的对象,制定不同的GC策略,降低整体内存管理的开销
      1. 年轻对象:存活对象少,一般用 Copying GC
      2. 老年对象:趋于一直或者,一般采用 Mark-sweep GC

引用计数

  1. 优点:内存管理的操作被平摊到程序执行过程
  2. 缺点:(巴拉巴拉一大堆😒)开销大,可能引发暂停

内存管理级优化

Go内存分配 - 分块

  1. 提前将内存分块,根据对象的大小,选择最合适的块返回

Go内存管理分配 - 缓存

image.png

Go内存管理优化

  1. Balanced GC image.png
    1. 多个小对象的分配合并成一次大对象的分配
    2. 本质:用Copying GC 管理小对象 image.png

编译器和静态分析

image.png

静态分析

  1. 静态分析:不执行程序代码,推导程序行为
  2. 控制流:程序执行的流程
  3. 数据流:数据在控制流上的传递
  4. 过程内分析:函数内部
  5. 过程间分析:考虑过程调用时参数的传递返回值的数据流和控制流

编译器优化

  1. 函数内联 image.png
  2. Beast Mode image.png 函数内联拓展了函数边界,更多对象不逃逸
    1. 逃逸分析 image.png