Go性能优化减少资源占用| 青训营

191 阅读3分钟

Go内存管理 目标:为对象在heap上分配内存

提前将内存分块

调用系统调用mmap( ),向OS申请一大块内存

先将内存划分成大块 mspan

再将大块继续划分成特定大小的小块,用于对象分配

noscan mspan :分配不包含指针的对象,GC不要扫描

scan mspan 分配包含指针的对象--GC需要扫描

对象分配:根据对象的大小,选择最合适的块返回

Go内存分配 - 缓存 TCMalloc:thread caching

每个p包含一个mcache用于快速分配,用于为绑定于p上的g分配对象

mache管理一组mspan

当mcache中的mspan分配完毕,向mcentral申请待有未分配块的mspan

当mspan中没有分配的对象,mspan会被缓存在mcentral中,而不是立刻释放并规划给OS

Go内存分配 - 分块 目标 为对象在heap上分配内存

提前将内存分块

调用系统调用mmap()向OS申请一大块内存

先将内存划分成大块

再将大块继续划分成特定大小的小块,用于对象分配

noscan mspan分配不包含指针的对象--GCbuxuyao1saomiao1

scan mspan分配包含指针的对象--GC需要扫描

对象分配:根绝对象的大小,选择最合适的块返回

Go内存管理优化 对象分配是非常高频的操作:每秒分配GB级别的内存

小对象占比高

Go内存分配耗时

分配路径长:g->m->p>mache->memory block->return poniter

pprof 对象分配的函数是最频繁调用的函数之一

优化方案 Balanced GC 每个g都绑定一大块内存

GAB用于noscan类型的小对象分配

使用三个指针维护GAB:base,end,stop

Bump poinyer(指针碰撞) 风格对象分配

无需和其他分配请求互斥

分配动作简单高效

Balanced GC GAB对于Go内存管理来说是一个大对象

本质:将多个小对象的分配合并成一次大对象的分配

问题:GAB的对象分配方式会导致内存被延迟释放

方案:移动GAB中存活的对象

当GAB总大小超过一定阈值时,将GAB中存活的对象复制到另外分配的GAB中

原先的GAB可以释放,避免内存泄露

本质:用copying GC 的算法管理小对象

根据对象的声明周期,使用不同的标记和清理策略

编译器和静态分析 编译器的结构 作用 重要的系统软件

识别符合语法和非法的程序‘

生成正确且高效的代码

分析部分 (前端 front end)

词法分析 生成词素

词法分析 生成语法树

语义分析,收集类型信息,进行语义检查

中间代码生成,声成intermediate representation(IR)

综合部分(后端 back end)

代码生成,机器无关优化,生成优化的IR

代码生成,生成目标代码