这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
本节内容:
性能优化与自动内存管理
Go的内存管理&编译器
性能优化是什么?
提升软件系统处理能力,减少不必要的消耗,充分发掘计算机算力。
为什么要做性能优化?
用户体验:
带来用户体验的提升——让刷抖音更丝滑,让双十一购物不再卡顿 资源高效利用:
降低成本,提高效率——很小的优化乘以海量机器会是显著的性能提升和成本节约
自动内存管理
动态内存
自动分配 maclloc()
自动内存管理(垃圾回收)
避免手动内存管理
保证内存使用的正确性和安全性
三个任务
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
相关概念(涉及到语言底层)
评价GC算法
- 安全性 不能回收存活的对象 基本要求
- 吞吐率 1-(GC时间)/(程序执行总时间)
- 暂停时间 业务是否感知
- 内存开销 GC元数据开销
追踪垃圾回收
对象被回收的条件:指针指向关系不可达的对象
标记根对象:静态变量,全局变量,常量,线程栈登
标记:找到可达对象
求指针指向关系的传递闭包:
清理:所有不可达对象
将存活对象复制到另外的内存空间(copying gc)
将死亡对象的内存标记为“可分配”(Mark——sweep Gc)
移动并整理存活对象(mark-compact gc)
分代gc
每个对象都有年龄:经历过gc的次数
年轻代
常规的对象分配
存活对象很少,采用copying collection
老年代
对象一直活着,反复复制开销大
采用mark-sweep collection
引用计数
每个对象都有与之关联的引用数目
对象存活的条件:当且仅当引用数大于0
优点
可以一边执行一边操作
缺点
维护引用计数的开销较大;通过原子操作保证对引用计数操作的原子性和可见性
不能回收环形的结构
Go的内存管理&编译器
分块
目标:为对象在heap上分配内存
提前将内存分块
先分大块,然后再分小块
缓存
对象分配是非常高频的操作:每秒分配GB级别的内存
小对象占比高
Go的内存分配比较耗时
编译器结构
静态分析
不去执行代码,推导此程序的行为,分析程序的性质
控制流:程序执行的流程
数据流:程序执行的流程
int a=30
int b=9-(a/5)
int c
c=b*4
if (c > 10){
c=c-10
}
return c*(60/a)
过程内分析和过程间分析
过程内分析下
仅在函数内部进行分析
过程间分析下
考虑过程调用的参数传递和返回值的数据流和控制流
函数内联
逃逸分析
课程总结
性能优化
- 自动内存管理
- GO的内存管理
- 编译器与静态分析
- 编译器优化
实践
- balanced gc 优化对象分配
- beast mode 提高代码性能
课程收获
这两节课非常的硬核,接触到了底层的东西,非常的有深度,网上的资料也很少,非常的nice