这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
这是我参与「第五届青训营 」的第 6 天
自动内存管理
Go 内存管理及优化
编译器和静态分析
Go 编译器优化
引言
什么是性能优化?
- 提升软件系统处理能力,减少不必要的消耗,充分发掘计算机算力
为什么要做性能优化?
- 用户体验:带来用户体验的提升 —— 让刷抖音更丝滑,让双十一购物不再卡顿
- 资源高效利用:降低成本,提高效率 —— 很小的优化乘以海量机器会是显著的性能提升和成本节约
性能优化的层面
业务层优化
- 针对特定场景,具体问题,具体分析
- 容易获得较大性能收益
语言运行时优化
- 解决更通用的性能问题
- 考虑更多场景
- Tradeoffs
数据驱动
- 自动化性能分析工具 —— pprof
- 依靠数据而非猜测
- 首先优化最大瓶颈
软件质量
- 软件质量至关重要
- 保证接口稳定的前提下改进实现
- 测试驱动:测试用例覆盖尽可能多的场景,方便回归
- 文档:通过清晰的文档告诉用户这一项优化做了什么,没做什么,能达到怎样的效果
- 隔离:优化代码用选项和原先的路径隔离,保证优化未启用时的行为同以前一致
- 可观测(必要的日志输出)、可灰度、可回滚
自动内存管理
基本概念
动态内存
- 程序在运行时根据需求动态分配的内存:
malloc()
自动内存管理(垃圾回收)
- 避免手动内存管理,专注于实现业务逻辑
- 保证内存使用的正确性和安全性:
double-free problem,use-after-free problem
三个任务
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
相关概念
Mutator: 业务线程,分配新对象,修改对象指向关系Collector:GC线程,找到存活对象,回收死亡对象的内存空间
Serial GC 算法
- 会有暂停
- 只有一个
collector
Parallel GC 算法
- 并行
GC,支持多个collectors同时回收的GC算法 - 性能比
Serial GC高一些
Concurrent GC
- 并发
GC,支持mutator(s)和collector(s)同时执行的GC算法 - 不用显示的暂停程序,需要时把
collector(s)唤醒,一边做垃圾回收一边用户线程还在执行着,等到GC做完后,再把其休眠掉,接着mutator(s)又可以同步进行了
- 挑战:Collectors 必须感知对象指向关系的改
评价GC算法
- 安全性(
Safety):不能回收存活的对象 基本要求 - 吞吐率(
Throughput): 花在GC上的时间(花在GC上的时间越少越好,所以吞吐量越大越好) - 暂停时间(
Pause time):stop the world(STW) 业务是否感知(暂停时间越短越好) - 内存开销(
Space overhead) GC元数据开销
追踪垃圾回收(Traing garbage collection)
copying GCMark-sweep GCCompact GC
分代GC
引用计数(Reference counting)
Go内存管理及优化
- 目标:为对象在heap上分配内存
- 提前将内存分块
Balanced GC