这是我参与「第五届青训营 」伴学笔记创作活动的第 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内存分配-缓存
go的对象分类路径很长,造成分配性能不好
编译器优化
编译器的结构
静态分析:不执行代码,推导程序行为
控制流 数据流
go编译器优化
函数内联
将被调用函数的函数体(callee)的副本替换到调用位置(caller)上,同时重写代码反应参数的绑定。
- 消除函数调用开销,如传递参数,保存寄存器
- 将过程间分析转化为过程内分析,有助于其他优化,逃逸分析
- 但是函数体变大,instrution canche不友好
- 编译成的go镜像变大
逃逸分析
逃逸分析:分析代码中指针的动态作用域,指针在何处可以被访问