Go 语言原理与实践课程-9 & 10
概述:内存优化和编译器优化
背景知识
性能优化的原因
优化的层次:业务层优化,语言运行时优化(本次重点)
优化的可维护性(测试、文档)
自动内存管理背景-go内存管理
概述:概念-标记垃圾回收&分代垃圾回收&引用计数
---->概念
mutator:业务线程,分配对象、修改对象指向关系(用户启动的、goroutine都算)
collector:GC线程
paralle:多个collector(相对于serial)
concurrent:collector和mutator同时
那么collector必须感知对象间指向关系的改变
---->评价标准
正确性:不能删除活的
吞吐率:1-GC和程序总时间比值
暂停时间、内存开销
推荐书籍-the garbage collection handbook
---->追踪的垃圾回收
步骤:标记根对象(栈、全局变量等等)-》标记可达对象-》清理不可达对象
清理的方法:copying GC、mark-sweep GC(只标记)、mark-compact GC(原地整理对象)
根据对象生命周期选择
---->分代垃圾回收
基于分代假说 ;年龄基于经过GC的次数;把不同对象放不同区域;不同区域不同策略:年轻代copying老年代mark-sweep
---->引用计数
优点:不打断程序+不需要了解运行时(如c++智能指针)
缺点:开销大并行需要原子+环形引用(weak_ptr)+内存开销+回收时需要暂停
GO内存分配与内存分配优化 class 10
概述:GO内存分配与内存分配优化
---->分块
向系统要大块如4M mspan 8K
每个mspan内部再划分块,不同mspan划分大小不同,还分为no-scan和scan mspan,看有没有指针GC要不要扫不扫描
---->缓存
mcache-mcentral
---->必要性
每秒很多次
小内存很多
路径很长 G M P mcache mspan memory block
---->字节怎么做
Balance GC
每个G绑定1kb的GAB(goroutine allocation buffer)区,分配给noscan&&<128b的对象
Base Top end指针碰撞分配
每个g都有所以不用原子
- 缺点:延迟释放
- 解决:GAB比较慢了就copy gc
编译器优化背景-go编译器优化
概述:编译器基本概念和静态分析(控制流和数据流、过程内和过程间分析)
---->编译器与编译过程
词法分析-----(词素lexeme)----语法分析----(抽象语法树AST)-----语义分析-----decorated AST----中间表示----IR(机器无关)-----(从这往后叫后端,具体主要讲后端)代码优化-----IR(机器无关)----代码生成---------目标代码
---->静态分析
不执行代码分析代码性质
控制流,数据流
过程内、过程间(包括函数返回等等)
---->编译器优化
为什么做:用户无感知&通用
怎么做:牺牲编译时间提高重复执行的代码的性能
方法:函数内联、逃逸分析、默认栈大小调整、边界检查消除、循环展开
---->函数内联
减少函数调用&过程间变成过程内供其他模块分析
例子是通过编译器参数让它不inline
分享:快速用benchmark去检查性能
缺点:函数体变大,cpu可能没法放一个patch,复制时太大等等。可以根据一些性质(如长短)决定是否内联
Beast mode(字节产品):解决了go 的保守内联策略,interface、defer
---->逃逸分析
概念:分析指针动态作用域,参数传递、传递给全局、传递给其他g,传递给已逃逸的对象
Beast mode:因为减少了内联所以也减少了逃逸(可以在栈上分配,减轻gc负担)