这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
Go 语言内存管理与编译优化课堂笔记
1 本次课堂的内容
本节课程主要分为两部分,分别是自动内存管理和Go内存管理及优化。第一部分讲解自动内存管理的相关概念及实现方式,第二部分则讲解Go内存管理及优化,包括编译器和静态分析,以及Go编译器优化。
2 详细知识点的介绍
2.1 性能优化
性能优化的目的是提升系统的处理能力,减少不必要的消耗,更有效地利用计算机资源。
进行性能优化的原因有很多,包括提高用户体验,提高效率以及降低成本等。比如说,在双十一购物时,优化性能可以让网站不再卡顿,提升用户体验;同时,优化性能还可以让系统更加高效地利用资源,降低成本。
性能优化分为三个层面:
- 业务层优化,针对特定场景进行具体分析,容易获得较大性能收益。
- 语言运行时优化,解决更通用的性能问题,考虑更多场景,需要在性能和其他因素之间进行权衡。
- 数据驱动优化,使用自动化性能分析工具,依靠数据而非猜测,首先优化最大瓶颈。
2.2 软件质量
软件质量保证是通过接口稳定性保证,测试驱动,清晰文档告知用户优化的目的和效果,以及隔离和可观测性等方式来实现的。
2.3 自动内存管理
自动内存管理是指由程序语言的运行时系统负责管理动态内存,避免手动内存管理,让开发人员能够专注于业务逻辑的实现。该系统还会保证内存使用的正确性和安全性,避免常见的问题如 double-free problem 和 use-after-free problem。
几个重要概念:
- Mutator: 业务线程,分配新对象,修改对象指向关系
- Collector: GC 线程,找到存活对象,回收死亡对象的内存空间
- Serial GC: 只有一个 collector
- Parallel GC: 并行 GC,支持多个 collectors 同时回收的 GC 算法
- Concurrent GC: 并发 GC,支持 mutator (s) 和 collector (s) 同时执行的 GC 算法
追踪垃圾回收
追踪垃圾回收: 一种通过标记和清理来回收不再使用的内存空间的方式。根据对象可达性来判断对象是否存活。其过程包括三个步骤:
- 标记:标记出所有可达对象,可达对象即为程序中所有引用的对象。
- 清理:回收所有不可达对象占用的内存空间。
- 整理:将存活对象整理到同一内存区域。
几种策略:
Copying GC: 将存活对象复制到新的内存空间,原来的空间可以直接进行对象分配。 Mark-sweep GC: 将死亡对象所在内存块标记为可分配,使用 free list 管理可分配的空间。 Mark-compact GC: 将存活对象复制到同一块内存区域的开头。
引用计数
引用计数是一种常见的自动内存管理技术。它的基本思想是为每个对象维护一个引用数目,并在程序运行过程中不断调整这个数目。当对象的引用数目为 0 时,系统就可以回收这个对象的内存。 好处在于:这种技术对程序员是透明的,不需要了解 runtime 的细节,也不需要手动管理内存。
缺点是,开销较大,因为对象可能会被多线程访问,对引用计数的修改需要原子操作保证原子性和可见性。此外一个对象的引用计数可能会被多线程修改,所以需要进行原子操作来保证原子性和可见性。这样会增加系统的开销。