Go语言内存管理优化 | 青训营笔记

46 阅读3分钟

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

一. 重点内容

  • 自动内存管理

  • Go语言内存管理及优化

  • 编译器和静态分析

  • Go语言编译器优化

二. 知识点介绍

1. 性能优化

  • 性能优化:提升软件系统处理能力,减少不必要的消耗,充分发掘计算机算力
  • 为什么要性能优化:提升用户体验;资源有效利用
  • 性能优化的层面:如业务层优化(容易获得较大性能收益)、语言运行时的优化以及数据驱动层面的优化

2. 自动内存管理

  • 动态内存:程序在运行时根据需求动态分配的内存:malloc()
  • 自动内存管理(垃圾回收):由系统管理动态内存
    • 避免手动内存管理,专注于实现业务逻辑
    • 保证内存使用的正确性和安全性: double-free problem, use-after-free problem
  • 相关概念
    • Mutator: 业务线程,分配新对象,修改对象指向关系
    • Collector: GC线程,找到存活对象,回收死亡对象的内存空间
    • Serial GC: 只有一个collector
    • Parallel GC: 并行GC,支持多个collectors同时回收的GC算法
    • Concurrent GC: 并发GC,支持mutator(s)和collector(s)可以同时执行的GC算法
  • GC算法:
    • Safety:不能回收存活的对象
    • Throughput:1 - GC时间/程序执行总时间
    • Pause time:stop the world(STW)
    • Space overhead:GC元数据开销
  • 追踪垃圾回收(Tracing garbage collection):根据对象的生命周期,使用不同的标记和清理策略
    • 对象被回收的条件:指针指向关系不可达的对象
    • 标记根对象 (GC roots): 静态变量、全局变量、常量、线程栈等
    • 标记:找到所有可达对象
    • 清理:回收所有不可达对象占据的内存空间
  • 引用计数
    • 每个对象都有一个与之关联的引用数目
    • 对象存活的条件:当且仅当引用数大于0
    • 优点:指针传递的过程中进行引用计数的增减;不需要了解 runtime 的细节
    • 缺点:开销大,因为对象可能会被多线程访问,需要用原子操作保证原子性和可见性;无法回收环形数据结构;每个对象都引入额外存储空间存储引用计数;回收大的数据结构可能引发程序的暂停

3. Go内存管理及优化

  • 目标:为对象在heap上分配内存(提前将内存分块)
  • 对象分配:根据对象的大小,选择最合适的块返回
  • 内存缓存:Go 内存管理构成了多级缓存机制,从OS分配得的内存被内存管理回收后,也不会立刻归还给OS,而是在Go runtime内部先缓存起来,从而避免频繁向OS申请内存。
  • 编译器和静态分析
    • 静态分析:不执行代码,推导程序的行为,分析程序的性质
    • 控制流:程序的执行流程
    • 数据流:数据在控制流上的传递