这是我参与「第五届青训营 」笔记创作活动的第3天
内存管理
自动内存管理
概念与背景
自动内存管理管理的是动态内存,是程序运行时根据需求分配的内存。而自动管理内存(垃圾回收)是程序语言的运行时系统管理内存,避免手动内存管理,专注于业务逻辑,降低开发成本,保证内存安全性和正确性。GC需要为对象分配空间,找到存活对象并回收死亡对象。
- Mutator:业务线程,分配新对象,修改对象指向关系
- collector:GC线程,找到存活对象,回收死亡对象内存空间
- Serial GC:只有一个GC
- Parallel GC:多个GC
- Concurrent GC:多个GC并且Mutator可以和Collector可以同时执行
Tracing GC
对象被回收的条件:指针指向关系不可达的对象
算法:
- 标记根对象:静态变量、常量等指针指向对象标记为存活
- 找到并标记可达对象:根据指针求指针指向关系闭包,找到所有可达对象
- 清理所有不可达对象:清理策略包括COPY GC(将存活对象复制到其他空间),Mark-Sweep(将死亡对象地址标记为可分配),Mark-compact GC(转移并整理存活对象)
Generational GC
分代假说:许多对象分配后很快就不被使用了
基于该假说,为对象设置“年龄”属性,每经过一次GC不被回收,年龄+1。对不同年龄对象置定不同GC策略,降低整体内存管理开销。
- 对于Young generation 常规的内存分配,由于存活的对象很少,可以采用Copy collect策略。
- 对于Old generation
老年代对象区趋于长期存在,反复复制开销很大,可以采用mark-sweap collection策略
Reference Counting
原理:每个对象都有与之关联的引用数目,对象存活条件是引用数大于0。
- 优点:
- 内存管理的操作平摊到执行过程中
- 内存管理不需要了解runtime实现细节
- 缺点
- 维护引用计数开销较大:原子操作
- 会有引用循环
- 每个对象需要增加内存空间存储引用数目
- 回收内存时可能引发
GO内存管理以及优化
对象分配
- go中对象分配是一个高频操作:每秒分配GB级别
- 小对象占比高
- GO内存分配耗时
基于以上特性,提出优化方案:Balanced GC
- 每个GOROUTINE绑定一块1KB内存,称为GAB,用于小对象分配
- 三个指针维护GAB:base,end,top(分别是基地址、尾地址、当前地址)
- Bump pointer风格对象分配
一个缺点是会导致内存延迟释放,解决方法是移动GAB中存活的对象。
小结
以上讲述了GO内存管理中自动内存管理和优化。主要是介绍底层原理。关于复杂的实现需要自己多熟悉。