Day11-go语言内存管理 & 编译器优化 | 青训营笔记

96 阅读2分钟

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

1 GO内存管理及优化

1.1 Go内存分配

1.1.1 分块

  • 为对象在heap堆上分配内存;

  • 提前将内存分块,选择合适大小的小块给对象分配;

image.png

1.1.2 缓存

  • g代表协程goroutie;
  • Go内存管理构成了多级缓存机制,从OS分配得到的内存被内存管理回收后,也不会立刻归还OS,而是在Go runtime内部缓存起来,从而避免频繁向OS申请内存;
  • 内存分配的路线图如下;

image.png

1.2 Go内存管理优化

  • 大多数是小对象的内存分配;

  • 但内存分配链比较长,分配比较耗时;

image.png

image.png

1.3 优化方案:Balanced GC

  • 通过给每个g(协程)绑定一块内存(1KB=1024B/字节)

  • 称为gotoutine allocation buffer(GAB)协程分配缓存;

  • 专门用于小对象分配<128B;

image.png

  • 当每个g上的内存存活对象较少时,就采用copying GC管理小对象

image.png

小结

image.png

2 编译器和静态分析

2.1 编译器结构

image.png

2.2 静态分析

  • 静态分析
    • 概念:不执行程序代码,推导程序的行为,分析程序的性质
    • 方法:
      • 1)控制流;
      • 2)数据流;

image.png

2.3 过程内分析和过程间分析

  • 过程内分析

    • 仅在函数内部进行分析;
  • 过程间分析:同时设计控制流和数据流,比较复杂

    • 过程调用
    • 参数传递和返回值的数据流和控制流;

image.png

3 Go编译器优化

  • go目前编译器采用优化较少,为了更少的编译时间,没有进行复杂代码分析和优化;

  • 优化:用编译时间换取更高效的机器码;

image.png

3.1 函数内联(inlining)

  • 内联:

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

image.png

image.png

  • 内联缺点:

  • 1)函数体变大,instruction 擦车(icache)不友好;

  • 2)编译生成的Go镜像变大;

3.2 Beast Mode

image.png

  • 逃逸分析
    • beast mode之后,函数内联扩展了函数边界,更多边界不逃逸;
    • 优化:未逃逸的对象可以在栈上分配;
      • 对象在栈上分配和回收很快,移动sp即可;
      • 减少在heap上分配,降低GC负担;

image.png