性能优化及自动内存管理 | 青训营笔记

129 阅读3分钟

性能优化及自动内存管理 | 青训营笔记

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

本节内容

Go 语言优化:

  • 内存管理优化
  • 编译器优化

性能优化

  • 性能优化是什么?
    • 提升软件系统处理能力,减少不必要的消耗,充分发掘计算机算力
  • 为什么要做性能优化?
    • 用户体验:带来用户体验的提升
    • 资源高效利用:降低成本,提高效率 很小的优化乘以海量机器会是显著的性能提升和成本节约
  • 性能优化的层面

image.png

  • 性能优化与软件质量 我们进行开发的都是Go SDK,需要保证接口的稳定性,也就是版本和版本之间,需要的参数等基本是不需要改变的。

image.png

自动内存管理

  • 动态内存:程序在运行时根据需求动态分配的内存:例如 malloc()
  • 自动内存管理(垃圾回收) : 由程序语言的运行时系统管理动态内存
    • 避免手动内存管理,专注于实现业务逻辑
    • 保证内存使用的正确性安全性,出现的问题例如:double-free problem use-after-free problem
  • 三个任务
    • 为新对象分配空间
    • 找到存活对象
    • 回收死亡对象的内存空间

相关概念

image.png

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

image.png

  • GC算法的评价
    • 安全性:不能回收存活对象 (基本要求
    • 吞吐率
    • 暂停时间
    • 内存开销:GC元数据开销
  • GC算法
    • 追踪垃圾回收
    • 引用计数

追踪垃圾回收

image.png

  • 对象被回收的条件:指针指向关系不可达的对象
  • 标记根对象
    • 静态变量、全局变量、常量、线程栈等(一定是存活的)
  • 标记:找到可达对象
  • 清理:所有不可达对象,也就是我们无法通过

清理策略 - Copying GC

*将对象复制到另外的内存空间

image.png

清理策略 - Mark-sweep GC

*使用 free list 管理空闲内存

image.png

就是将这些被标记的元素利用free list 链接起来,然后再进行新的内存分配的时候从这个链当中进行分配就可以了。

清理策略 - Compact GC

*原地整理对象

image.png

将存活的对象拷贝到内存开始的地方进行压缩,之后从后面开始分配就可以了

*我们需要根据对象不同的生命周期来使用不同的分配方式

分代GC

image.png

image.png

引用计数

  • 每个对象都有一个与之关联的引用数目
  • 对象存活的条件:当且仅当引用数大于0
  • 优点:
    • 内存管理的操作被平摊到程序执行过程当中
    • 内存管理不需要了解runtime的实现细节:C++智能指针(smart pointer)
  • 缺点:
    • 维护引用计数开销较大:通过原子操作保证对引用计数操作的原子性和可见性
    • 无法回收环形数据结构 - weak reference
    • 内存开销:每个对象都引入的额外内存空间存储引用数目
    • 回收内存时依然可能引发暂停

Go内存分配

分块

image.png

  • 目标:为对象在heap上分配内存
  • 提前将内存分块
    • 调用系统调用mmap() 向OS申请一大块内存
    • 先将内存划分成大块
    • 再将大块继续划分成特定大小的小块,用于对象分配
    • noscan mspan:分配不包含指针对象 -- GC不需要扫描
    • scan mspan:分配包含指针的对象 -- GC需要扫描
  • 对象分配:根据对象的大小,选择最合适的块返回

缓存

image.png

image.png