Go内存管理和编译器优化 | 青训营笔记

62 阅读2分钟

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

一、课程内容

  • Go内存分配
  • Go内存管理优化

二、详细知识点

1、Go内存分配

分块

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

对象分配:提前将内存分块,根据对象的大小,选择最合适的块返回

缓存

线程缓存、中心缓存

2、内存管理优化

Balanced GC

每个g都绑定1KB内存,称作goroutine allocation buffer(GAB)

用三个指针维护GAB

image.png 优点:无需和其他分配请求互斥、分配动作简单高效

问题:GAB本质是将多个小对象的分配合并成一次达对象的分配,所以GAB对于Go内存管理来说是一个大对象,它的分配方式可能导致内存被延迟释放。

解决方案:当GAB总大小超过一定阈值时,将GAB中存活的对象复制到另外的GAB中,释放原先的GAB,避免内存泄露。

3、编译器优化

内联

将被调用函数的函数体的副本替换到调用位置上,同时重写代码以反应参数的绑定 优点:

  • 消除函数调用开销
  • 将过程间分析转化为过程内存分析,帮助其他优化

Beast Mode

语言特性,Go函数内联受到的限制较多,内联策略非常保守,限制了函数内联

调整内联策略,使更多函数被内联,可以降低函数调用的开销,增加了其他优化的机会

但同时也会带来一定开销,比如编译时间增加

逃逸分析

Go语言中,编译器决定内存分配位置的方式就是逃逸分析。

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

思路:从对象分配处出发,观察对象数据流

优化方式:未逃逸的对象可以在栈上分配,这样分配和回收的速度都快,减少了在heap上的分配,降低GC负担

三、总结

这次课程对Go内存分配和编译器相关知识进行了展开,通过对内存管理的优化和编译器的优化,可以让我们的服务拥有更好的性能。