Golang 内存分配与逃逸分析

参考:灵魂拷问:Go 语言这个变量到底分配到哪里了?

来源于 公众号: 脑子进煎鱼了 ,作者陈煎鱼。


我们在写代码的时候,有时候会想这个变量到底分配到哪里了?这时候可能会有人说,在栈上,在堆上。信我准没错…
但从结果上来讲你还是一知半解,这可不行,万一被人懵了呢。今天我们一起来深挖下 Go 在这块的奥妙,自己动手丰衣足食!

问题

type User struct {
   
 ID     int64
 Name   string
 Avatar string
}

func GetUserInfo() *User {
   
 return &User{
   ID: 13746731, Name: "EDDYCJY", Avatar: "https://avatars0.githubusercontent.com/u/13746731"}
}

func main() {
   
 _ = GetUserInfo()
}

开局就是一把问号,带着问题进行学习。请问 main 调用 GetUserInfo 后返回的 &User{…}。这个变量是分配到栈上了呢,还是分配到堆上了?

什么是堆/栈

在这里并不打算详细介绍堆栈,仅简单介绍本文所需的基础知识。如下:

  • 堆(Heap):一般来讲是人为手动进行管理,手动申请、分配、释放。一般所涉及的内存大小并不定,一般会存放较大的对象。另外其分配相对慢,涉及到的指令动作也相对多。
  • 栈(Stack):由编译器进行管理,自动申请、分配、释放。一般不会太大,我们常见的函数参数(不同平台允许存放的数量不同),局部变量等等都会存放在栈上。

今天我们介绍的 Go 语言,它的堆栈分配是通过 Compiler 进行分析,GC 去管理的,而对其的分析选择动作就是今天探讨的重点。

什么是逃逸分析

在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法,简单来说就是分析在程序的哪些地方可以访问到该指针。

通俗地讲,逃逸分析就是确定一个变量要放堆上还是栈上,规则如下:

  1. 是否有在**其他地方(非局部)**被引用。只要有可能被引用了,那么它一定分配到堆上。否则分配到栈上。
  2. 即使没有被外部引用,但对象过大,无法存放在栈区上。依然有可能分配到堆上。

对此你可以理解为,逃逸分析是编译器用于决定变量分配到堆上还是栈上的一种行为。

在什么阶段确立逃逸

编译阶段确立逃逸,注意并不是在运行时。

为什么需要逃逸

这个问题我们可以反过来想,如果变量都分配到堆上了会出现什么事情?例如:

  • 垃圾回收(GC)的压力不断增大。
  • 申请、分配、回收内存的系统开销增大(相对于栈)。
  • 动态分配产生一定量的内存碎片。

简单来说,就是频繁申请并分配堆内存是有一定 “代价” 的。会影响应用程序运行的效率,间接影响到整体系统

因此 “按需分配” 最大限度的灵活利用资源,才是正确的治理之道。这就是为什么需要逃逸分析的原因,你觉得呢?

怎么确定是否逃逸

第一,通过编译器命令,就可以看到详细的逃逸分析过程。而指令集 -gcflags 用于将标识参数传递给 Go 编译器,涉及如下:

-m 会打印出逃逸分析的优化策略,实际上最多总共可以用 4 个 -m,但是信息量较大,一般用 1 个就可以了。

-l 会禁用函数内联,在这里禁用掉 inline 能更好的观察逃逸情况,减少干扰。

$ go build -gcflags '-m -l' main.go

第二,通过反编译命令查看

$ go tool compile -S main.go

注:可以通过 go tool compile -help 查看所有允许传递给编译器的标识参数。

逃逸案例

案例一:指针

第一个案例是一开始抛出的问题,现在你再看看,想想,如下:

type User struct {
   
 ID     int64
 Name   string
 Avatar string
}

func GetUserInfo() *User {
   
 return &User{
   ID: 13746731, Name: "EDDYCJY"
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值