Go 语言内存管理详解|青训营笔记

145 阅读4分钟

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

1.课前预习相关重要概念

自动内存管理

  • Auto memory management: 自动内存管理

    程序运行时系统自动管理内存,避免手动管理内存,使得我们可以专注于实现业务逻辑

  • Grabage collction: 垃圾回收(GC)

    垃圾回收是一种自动管理内存的方式,支持GC的语言无需手动管理内存,程序后台自动判断对象是否存活并回收其内存空间,使开发人员从内存管理上解脱出来

  • Mutator: 业务线程
  • Collector: GC 线程
  • Concurrent GC: 并发 GC
  • Parallel GC: 并行 GC
  • Tracing garbage collection: 追踪垃圾回收

    • Copying GC: 复制对象 GC
    • Mark-sweep GC: 标记-清理 GC
    • Mark-compact GC: 标记-压缩 GC
  • Reference counting: 引用计数

    一种实现GC的算法

  • Generational GC: 分代 GC

    • Young generation: 年轻代
    • Old generation: 老年代

Go 内存管理及优化

  • TCMalloc
  • mmap() 系统调用
  • scan object 和 noscan object
  • mspan, mcache, mentral
  • Bump-pointer object allocation: 指针碰撞风格的对象分配

编译器和静态分析

  • 词法分析
  • 语法分析
  • 语义分析
  • Intermediate representation (IR) 中间表示
  • 代码优化
  • 代码生成
  • Control flow: 控制流
  • Data flow: 数据流
  • Intra-procedural analysis 过程内分析
  • Inter-procedural analysis: 过程间分析

Go 编译器优化

  • Function inlining: 函数内联
  • Escape analysis: 逃逸分析

上节课回顾

问题:pprof采样原理?

————————————————————————————课程开始分割线

Go语言优化

什么是性能优化?

为什么要做性能优化?

image.png

性能优化的层面

  • 业务代码
  • SDK
  • 基础库
  • 语言运行时
  • OS

主要有两种优化:业务层优化 语言运行时优化

内存管理优化

编译器优化

Go SDK

image.png

1.自动内存管理

image.png

GC可以保证内存使用的正确性和安全性

GC的三个任务

1.为对象分配空间

2.找到存活对象

3.回收死亡对象的内存

三种GC的执行方式,其中前两种都需要暂停业务线程

第三种可以让业务线程和GC线程同时执行

image.png

Concurrent GC也存在问题:

image.png

它必须要感知到对象指向关系的改变,否则就会出错

如图,b对象是在GC过程中新加入的对象,GC必须要将它也标记为存活的,否则就会出错

评价GC算法

image.png

两种常见的GC技术

1.追踪垃圾回收

对象被回收的条件,指针指向关系不可达的对象

流程:

标记根对象

标记:所有可达对象

清理:所有不 可达对象

一些清理策略(如何选择?需要根据对象的生命周期,使用不同的标记和清理策略)

Copying GC: 将当前区域存活的对象复制到另外的内存空间去,这样,原来的区域就可以被清空了

image.png

Mark-sweep GC: 将死亡对象的内存空间用一个free list管理起来,下次分配内存时,直接通过free list找一个块即可

image.png

Compact GC:将存活的对象拷贝到内存最开始的地方(原地整理对象),它和copying GC很像,只不过拷贝到的地方不一样

image.png

2.引用计数

每个对象都有一个与之关联的引用数字

对象存活条件:引用数字大于0

优点:

1.内存管理的操作被平摊到程序执行过程中

2.内存管理不需要了解runtime的实现细节

缺点:

image.png

2.Go 内存管理及优化

2.1 内存分配——分块

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

image.png

2.3 字节的优化方案——Balanced GC

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

GAB用于noscan类型的小对象分配:<128B

使用三个指针维护这个g

image.png

分配的处理只是移动指针,非常高效

GAB本质上就是将多个小对象的分配合并成一个大对象的分配

3.编译器和静态分析

经典编译器结构

image.png

image.png

3.2 静态分析

不执行代码,推导程序的行为

4.Go 编译器优化

函数内联、逃逸分析

4.1 函数内联

将要调用的函数直接拷贝到对应的位置上,相当于不用调用了?直接用

性能优化非常明显

image.png

image.png

4.2 逃逸分析

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

具体思路

image.png