这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
性能优化可分为业务层优化和语言运行时优化。在前一篇关于性能优化的笔记中,更多提到的是业务层的性能优化,在了解语言运行时优化之前,本文将对自动内存管理的概念和常见方法进行简单介绍。
概念
自动内存管理,又称垃圾回收(garbage collection),是由程序语言的运行时系统管理动态内存,不仅能避免开发者手动管理内存,而且能保证内存使用的正确性和安全性。
自动内存管理有三个核心的任务:
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
完成任务以上任务可采用不同的GC算法,下面将简单介绍三种:
在介绍算法前先介绍两个下面用到的概念:
**Mutator:**业务线程,分配新对象,修改对象指向关系
**Collector:**GC线程,找到存活对象,回收死亡对象的内存空间
- Serial GC
只有一个Collector。当需要进行GC操作时,先暂停所有Mutator,再用一个Collector去进行内存的标记和回收,最后当GC操作结束后就恢复所有Mutator的执行。
- Parallel GC
支持多个Collector同时回收。当需要进行GC操作时,先暂停所有Mutator,再用多个Collector去同步进行内存的标记和回收,最后当GC操作结束后就恢复所有Mutator的执行。
- Concurrent GC
mutator(s)和collector(s)可以**同时执行。**当需要进行GC操作时,可以一边collector进行内存的标记和回收,一边mutator继续执行,最后当GC操作结束后就休眠collector,mutator能够继续同步执行。相较前两种GC,这里的Collectors必须要能够感知对象指向关系的改变。
常见方法
追踪垃圾回收
回收条件:指针指向关系不可达的对象
回收步骤:
- 标记根对象,例如静态变量、全局变量、常量、线程栈等
- 从根对象出发,找到所有可达对象
- 清理所有不可达的对象,不同情形下清理策略可能不同,下面将简单介绍三种清理策略:
- Copying GC:将对象复制到另外的内存空间
- Mark-sweep GC:使用free list 管理空闲内存
- Mark-compact GC:原地整理对象
清理策略的选择是依据对象的生命周期进行的
引用计数
每个对象都有一个与之关联的引用数目。
回收条件:引用数=0
优点:
- 内存管理操作被平摊到程序执行过程中
- 内存管理不需要了解runtime的实现细节
缺点:
- 维护引用计数的开销较大
- 无法回收环形数据结构
- 需额外空间计数,增大内存开销
- 回收内存时依然可能引发暂停
总结
垃圾回收对于开发者来说是自动化且不可见的,但这并不表明我们不需要关注它。通过学习发现,垃圾回收的过程其实并不简单也有许多算法。所有对于开发者来说,我们也需要关注内存管理,了解其原理后选择适合的自动内存管理方式也是很有必要的。