这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
在学习了高质量编程之后,接着学习如何对代码进行性能优化,而想要知道优化的方法就需要先了解Go语言的内存管理机制
优化其实就是提升系统处理能力,减少不必要的消耗以及充分发掘计算机能力
优化的目的其实是为了提升用户的体验以及降低成本,提高效率和资源利用率
Go语言提供了内存管理机制,也就是垃圾回收(GC)。Go语言中的内存管理也就是管理程序在运行时需要配分的内存。GC的好处是不用开发者手动释放内存,专注于业务的实现,并且能够保证内存使用的正确性和安全性
GC有三种算法
serial GC(串行垃圾收集器):顾名思义,这种垃圾回收算法只有一个GC线程,GC线程的作用是找到内存中存活的对象,回收死亡对象的内存空间
Parallel GC(并行垃圾收集器):意思是有多个GC同时进行内存的回收
Concurrent GC(并发垃圾收集器):在业务线程执行的时候同时进行着垃圾回收工作
前两者和并发GC的最大差别就是当前两者进行GC时业务线程是停止执行的,也就是STW。STW是在垃圾回收过程中为了保证实现的正确性,防止无止境的内存增长等问题而不可避免的需要停止赋值器进一步操作对象图的一段过程
垃圾回收主要有两种算法
追踪垃圾回收
在此算法中回收的都是指针指向关系不可达的对象。具体的步骤是
- 标记根对象:静态变量、全局变量、常量、线程栈等
- 根据标记的根对象找出其所有的指向对象,找出所有可达对象
- 清理所有的不可达对象
其中,清理的做法又分为三种
- Copying GC:申请额外的内存空间来保存存活的对象,多用于常规的对象分配
- Mark-sweep GC:将死亡的对象标记为可分配,这样子下次需要分配内存时则直接从这些死亡对象中查找是否有满足要求的内存,多用于趋于一直存活的对象
- Mark-compact GC:把所有存活的对象移动、堆叠到一起,这样子就能保证不会存在内部碎片,增大了可分配内存的连续性,但可能操作的复杂度偏高
会根据对象的生命周期选择不同的标记,使用不同的清理策略
引用计数
此算法清理的是引用计数为0的对象。每个对象都会额外开辟一个空间来存储指向其的指针数,称为引用数目
优点就是在程序执行过程中随时可能出现引用数目为0的,因此在程序执行时就会执行内存管理
缺点就是为了保证操作的准确性,需要使用原子操作维护对引用计数的操作,并且无法回收环形的数据结构,可以理解为形成了死锁