Go 语言内存管理与编译优化 | 青训营笔记

84 阅读3分钟

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

Go 语言内存管理与编译优化课堂笔记

1 本次课堂的内容

本节课程主要分为两部分,分别是自动内存管理和Go内存管理及优化。第一部分讲解自动内存管理的相关概念及实现方式,第二部分则讲解Go内存管理及优化,包括编译器和静态分析,以及Go编译器优化。

2 详细知识点的介绍

2.1 性能优化

性能优化的目的是提升系统的处理能力,减少不必要的消耗,更有效地利用计算机资源。

进行性能优化的原因有很多,包括提高用户体验,提高效率以及降低成本等。比如说,在双十一购物时,优化性能可以让网站不再卡顿,提升用户体验;同时,优化性能还可以让系统更加高效地利用资源,降低成本。

性能优化分为三个层面:

  1. 业务层优化,针对特定场景进行具体分析,容易获得较大性能收益。
  2. 语言运行时优化,解决更通用的性能问题,考虑更多场景,需要在性能和其他因素之间进行权衡。
  3. 数据驱动优化,使用自动化性能分析工具,依靠数据而非猜测,首先优化最大瓶颈。

2.2 软件质量

软件质量保证是通过接口稳定性保证,测试驱动,清晰文档告知用户优化的目的和效果,以及隔离和可观测性等方式来实现的。

2.3 自动内存管理

自动内存管理是指由程序语言的运行时系统负责管理动态内存,避免手动内存管理,让开发人员能够专注于业务逻辑的实现。该系统还会保证内存使用的正确性和安全性,避免常见的问题如 double-free problem 和 use-after-free problem。

几个重要概念:

  1. Mutator: 业务线程,分配新对象,修改对象指向关系
  2. Collector: GC 线程,找到存活对象,回收死亡对象的内存空间
  3. Serial GC: 只有一个 collector
  4. Parallel GC: 并行 GC,支持多个 collectors 同时回收的 GC 算法
  5. Concurrent GC: 并发 GC,支持 mutator (s) 和 collector (s) 同时执行的 GC 算法

追踪垃圾回收

追踪垃圾回收: 一种通过标记和清理来回收不再使用的内存空间的方式。根据对象可达性来判断对象是否存活。其过程包括三个步骤:

  1. 标记:标记出所有可达对象,可达对象即为程序中所有引用的对象。
  2. 清理:回收所有不可达对象占用的内存空间。
  3. 整理:将存活对象整理到同一内存区域。

几种策略:

Copying GC: 将存活对象复制到新的内存空间,原来的空间可以直接进行对象分配。 Mark-sweep GC: 将死亡对象所在内存块标记为可分配,使用 free list 管理可分配的空间。 Mark-compact GC: 将存活对象复制到同一块内存区域的开头。

引用计数

引用计数是一种常见的自动内存管理技术。它的基本思想是为每个对象维护一个引用数目,并在程序运行过程中不断调整这个数目。当对象的引用数目为 0 时,系统就可以回收这个对象的内存。 好处在于:这种技术对程序员是透明的,不需要了解 runtime 的细节,也不需要手动管理内存。

缺点是,开销较大,因为对象可能会被多线程访问,对引用计数的修改需要原子操作保证原子性和可见性。此外一个对象的引用计数可能会被多线程修改,所以需要进行原子操作来保证原子性和可见性。这样会增加系统的开销。