“这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天”
1 GO内存管理及优化
1.1 Go内存分配
1.1.1 分块
为对象在heap堆上分配内存;
提前将内存分块,选择合适大小的小块给对象分配;
1.1.2 缓存
- g代表协程goroutie;
- Go内存管理构成了多级缓存机制,从OS分配得到的内存被内存管理回收后,也不会立刻归还OS,而是在Go runtime内部缓存起来,从而避免频繁向OS申请内存;
- 内存分配的路线图如下;
1.2 Go内存管理优化
大多数是小对象的内存分配;
但内存分配链比较长,分配比较耗时;
1.3 优化方案:Balanced GC
通过给每个g(协程)绑定一块内存(1KB=1024B/字节)
称为gotoutine allocation buffer(GAB)协程分配缓存;
专门用于小对象分配<128B;
- 当每个g上的内存存活对象较少时,就采用copying GC管理小对象
小结
2 编译器和静态分析
2.1 编译器结构
2.2 静态分析
- 静态分析
- 概念:不执行程序代码,推导程序的行为,分析程序的性质
- 方法:
- 1)控制流;
- 2)数据流;
2.3 过程内分析和过程间分析
-
过程内分析
- 仅在函数内部进行分析;
-
过程间分析:同时设计控制流和数据流,比较复杂
- 过程调用
- 参数传递和返回值的数据流和控制流;
3 Go编译器优化
go目前编译器采用优化较少,为了更少的编译时间,没有进行复杂代码分析和优化;
优化:用编译时间换取更高效的机器码;
3.1 函数内联(inlining)
内联:
将被调用的函数体的副本替换到调用位置上,同时重写代码也反映参数的绑定;
内联缺点:
1)函数体变大,instruction 擦车(icache)不友好;
2)编译生成的Go镜像变大;
3.2 Beast Mode
- 逃逸分析
- beast mode之后,函数内联扩展了函数边界,更多边界不逃逸;
- 优化:未逃逸的对象可以在栈上分配;
- 对象在栈上分配和回收很快,移动sp即可;
- 减少在heap上分配,降低GC负担;