Go语言 - 内存管理

1.自动内存管理

又称GC,保证内存使用的正确性与安全性

任务:

为新对象分配内存, 找到存活对象, 回收死亡对象的内存空间

GC的一些概念:

Mutator:业务线程,分配新对象,修改对象指向关系

Collector:GC线程,找到存活对象,回收死亡对象的内存空间,必须感知对象指向关系的改变,防止父对象被回收而子对象没有被回收

Serial GC:只有一个collector执行

Parrallel GC:支持多个collector同时回收GC

Concurrent GC:mutator(s) 和collector(s)可以同时执行

追踪GC:

1.标记根对象(堆,栈,全局变量区)

2.找到可达对象(保留下来的变量,将1, 2标记为存活对象,没被标记的为回收对象)

3.清理不可达对象,有以下方法,根据对象周期来选择不同策略

copying gc:将回收对象剪切到另外的内存空间

mark-sweep gc:将回收对象内存标记为可分配

compact gc:原地整理内存空间

GC策略:

1.分代GC,每经过一次GC且存活后,年龄 + 1,为年轻代与老年代分区。

对年轻代使用copying gc,老年代使用mark-sweep gc,以增加吞吐量

2.引用计数,每被引用,引用数 + 1,优先回收引用数为0的对象

实例是c++11的智能指针

优点是内存操作平摊到了程序执行种,缺点是开销大,无法回收环形结构,依然可能引发暂停

缺点是可以解决的,并非固有的缺点。

2.Go内存管理及优化

Go内存分配:

提前向OS申请一大块内存,在其划分为大块,再继续划分为特定大小的小块,用于对象分配

Go缓存TCMalloc(thread caching):

用于快速为对象分配内存空间

 堆内存管理优化:

为海量小型对象(<128B)分配内存地址,是十分耗时的工作

Balanced GC: 放弃g - m - p路径的内存分配方式,而是为g绑定一大块内存(1KB),使用三个指针维护,base,end,top,只需移动top指针来维护内存。(针对小对象noscan的优化策略)

noscan:不包含指针的对象

bitmap:便于快速寻址

 回收小对象使用copying gc,以防止一个小对象阻碍一个gab的回收。

3.编译器和静态分析

 编译器执行流程:
Go 语言编译过程概述 | Go 语言设计与实现icon-default.png?t=M4ADhttps://draveness.me/golang/docs/part1-prerequisite/ch02-compile/golang-compile-intro/静态分析:

属于编译器后端,不执行程序代码,推导程序行为。分为控制流与数据流

过程内分析与过程间分析:

  • Intra-procedural analysis: 函数内分析:在函数内进行控制流和数据流的分析
  • Inter-procedural analysis: 函数间分析:除了函数内的分析,还需要考虑跨函数的数据流和控制流,例如参数传递,函数返回值等

4.Go编译器优化

函数内联:

内联:编译时将被调用函数的函数体的副本替换到调用位置上,同时重写代码以反映参数的绑定

优点:减少开销,将过程间分析转换为过程内分析

缺点:编译过大

大多数情况内联是正向优化

逃逸分析:

  • 定义:分析代码中指针的动态作用域,即指针在何处可以被访问
  • 大致思路

  • 从对象分配处出发,沿着控制流,观察数据流。若发现指针 p 在当前作用域 s:

    • 作为参数传递给其他函数;
    • 传递给全局变量;
    • 传递给其他的 goroutine;
    • 传递给已逃逸的指针指向的对象;
  • 则指针 p 逃逸出 s,反之则没有逃逸出 s.

  • 优化:未逃逸出当前函数的指针指向的对象可以在栈上分配

    • 对象在栈上分配和回收很快:移动 sp 即可完成内存的分配和回收;
    • 减少在堆上分配对象,降低 GC 负担。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值