Go语言性能优化与自动内存管理 | 青训营笔记

73 阅读2分钟

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

# go语言性能优化与自动内存管理

内存管理优化

自动内存管理

为新对象分配空间,找到存活对象,回收死亡对象的空间

  • Mutator:业务线程,分配新对象,修改对象指向关系
  • Collector:GC线程,找到存活对象,回收死亡对象的内存空间

算法分类

  • Serial GC:只有一个collector
  • parallel GC:支持多个collectors同时回收的GC算法
  • Concurrent GC:mutator和collectors同时执行

追踪垃圾回收

  • 首先标记根对象(静态变量,全局变量,常量,线程栈)
  • 标记,找到可达对象:从根出发,找到所有可达对象
  • 清理:清理所有不可达的对象 Copying GC:将对象复制到另外的内存空间 Mark-sweep GC:使用free list管理空闲空间 Compact GC:原地整理对象

引用技术

对象存活条件:当且仅当引用数大于0

优点:

  • 内存管理被平摊到了程序执行过程
  • 内存管理不需要了解runtime实现细节 缺点:
  • 开销大:得原子操作
  • 无法回收环形数据结构
  • 内存开销:引用数目额外存储
  • 回收内存可能引发暂停

Go内存管理优化

Go提前对内存分块,mmap()申请4MB内存,然后将内存分类mspan 8KB,继续对mspan进行分块。

mspan分为两类,no scan mspan,不包含指针,GC不需要扫描;scan mspan,包含指针,需要扫描

Go内存分配-缓存

image.png

go的对象分类路径很长,造成分配性能不好

编译器优化

编译器的结构

image.png

静态分析:不执行代码,推导程序行为

控制流 数据流

go编译器优化

函数内联

将被调用函数的函数体(callee)的副本替换到调用位置(caller)上,同时重写代码反应参数的绑定。

  • 消除函数调用开销,如传递参数,保存寄存器
  • 将过程间分析转化为过程内分析,有助于其他优化,逃逸分析
  • 但是函数体变大,instrution canche不友好
  • 编译成的go镜像变大

逃逸分析

逃逸分析:分析代码中指针的动态作用域,指针在何处可以被访问