后端 golang内存与编译器 | 青训营笔记

97 阅读1分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

分块

  • 目标:在heap上为对象分配内存
  • 分块
    • 调用系统调用mmap()申请一块大内存4MB
    • 分成大块,mspan
    • 再将大块分成特定大小,分配给对象
    • nocan mspan:不包含指针---GC不扫描
    • scan mspan:包含指针---GC需要扫描
  • 对象分配:根据对象的大小,选择合适大小返回

缓存

使用缓存加快内存分配

  • mcache管理一组mspan
  • 当mspan分配完毕,向mcentral申请mspan
  • 当mspan中没有对象,不会立刻归还给OS,而是缓存在mcentral中

管理优化

  • 内存分配耗时
    • g->m->p->mcache->mspan->memory block->return pointer
    • pprof: 对象分配的函数是最频繁调用的函数之一

Balanced GC

  • 每个g都绑定一大块内存(1KB),称作goroutine allocation buffer(GAB)
  • 用于小对象分配(128 B)
  • 使用三个指针进行维护(base,end,top)
  • 本质:将多个小对象的分配合并成一次大对象的分配

静态分析

  • 不执行代码,但分析代码,推导程序行为
  • 通过控制流和数据流推导程序性质,进而优化代码
  • 过程内分析和过程间分析

编译器优化

函数内联

  • 将被调用函数的函数体(callee)的副本替换到调用位置(caller)上,同时重写代码以反映参数的绑定

逃逸分析

  • 分析代码中指针的动态作用域:指针在何处可以被访问